crashdump_uploader: fix memory leaks & use-after-frees
These `GoogleCrashdumpUploader` instances need to be cleaned up; place them on the stack. Doing this unmasks another bug in this code: the `MockLibcurlWrapper` instance we're passing into these `GoogleCrashdumpUploader`s becomes owned by the `GoogleCrashdumpUploader` in question. Putting them on the stack makes `free()` unhappy when the `GoogleCrashdumpUploader` they're given to gets destructed. Bug: b:235999011 Change-Id: I5d0424a1c09d32ea34a8fa6f5e52d3695ee6e857 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3756172 Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
parent
4d7cd09800
commit
9a1941fab9
3 changed files with 47 additions and 71 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "common/using_std_string.h"
|
#include "common/using_std_string.h"
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
|
||||||
const string& crash_server,
|
const string& crash_server,
|
||||||
const string& proxy_host,
|
const string& proxy_host,
|
||||||
const string& proxy_userpassword) {
|
const string& proxy_userpassword) {
|
||||||
LibcurlWrapper* http_layer = new LibcurlWrapper();
|
std::unique_ptr<LibcurlWrapper> http_layer{new LibcurlWrapper()};
|
||||||
Init(product,
|
Init(product,
|
||||||
version,
|
version,
|
||||||
guid,
|
guid,
|
||||||
|
@ -63,10 +64,11 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
|
||||||
crash_server,
|
crash_server,
|
||||||
proxy_host,
|
proxy_host,
|
||||||
proxy_userpassword,
|
proxy_userpassword,
|
||||||
http_layer);
|
std::move(http_layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
|
GoogleCrashdumpUploader::GoogleCrashdumpUploader(
|
||||||
|
const string& product,
|
||||||
const string& version,
|
const string& version,
|
||||||
const string& guid,
|
const string& guid,
|
||||||
const string& ptime,
|
const string& ptime,
|
||||||
|
@ -77,7 +79,7 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
|
||||||
const string& crash_server,
|
const string& crash_server,
|
||||||
const string& proxy_host,
|
const string& proxy_host,
|
||||||
const string& proxy_userpassword,
|
const string& proxy_userpassword,
|
||||||
LibcurlWrapper* http_layer) {
|
std::unique_ptr<LibcurlWrapper> http_layer) {
|
||||||
Init(product,
|
Init(product,
|
||||||
version,
|
version,
|
||||||
guid,
|
guid,
|
||||||
|
@ -89,7 +91,7 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
|
||||||
crash_server,
|
crash_server,
|
||||||
proxy_host,
|
proxy_host,
|
||||||
proxy_userpassword,
|
proxy_userpassword,
|
||||||
http_layer);
|
std::move(http_layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GoogleCrashdumpUploader::Init(const string& product,
|
void GoogleCrashdumpUploader::Init(const string& product,
|
||||||
|
@ -103,7 +105,7 @@ void GoogleCrashdumpUploader::Init(const string& product,
|
||||||
const string& crash_server,
|
const string& crash_server,
|
||||||
const string& proxy_host,
|
const string& proxy_host,
|
||||||
const string& proxy_userpassword,
|
const string& proxy_userpassword,
|
||||||
LibcurlWrapper* http_layer) {
|
std::unique_ptr<LibcurlWrapper> http_layer) {
|
||||||
product_ = product;
|
product_ = product;
|
||||||
version_ = version;
|
version_ = version;
|
||||||
guid_ = guid;
|
guid_ = guid;
|
||||||
|
@ -111,7 +113,7 @@ void GoogleCrashdumpUploader::Init(const string& product,
|
||||||
ctime_ = ctime;
|
ctime_ = ctime;
|
||||||
email_ = email;
|
email_ = email;
|
||||||
comments_ = comments;
|
comments_ = comments;
|
||||||
http_layer_.reset(http_layer);
|
http_layer_ = std::move(http_layer);
|
||||||
|
|
||||||
crash_server_ = crash_server;
|
crash_server_ = crash_server;
|
||||||
proxy_host_ = proxy_host;
|
proxy_host_ = proxy_host;
|
||||||
|
|
|
@ -31,11 +31,11 @@
|
||||||
#ifndef COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
|
#ifndef COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
|
||||||
#define COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
|
#define COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "common/linux/libcurl_wrapper.h"
|
#include "common/linux/libcurl_wrapper.h"
|
||||||
#include "common/scoped_ptr.h"
|
|
||||||
#include "common/using_std_string.h"
|
#include "common/using_std_string.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
@ -65,7 +65,7 @@ class GoogleCrashdumpUploader {
|
||||||
const string& crash_server,
|
const string& crash_server,
|
||||||
const string& proxy_host,
|
const string& proxy_host,
|
||||||
const string& proxy_userpassword,
|
const string& proxy_userpassword,
|
||||||
LibcurlWrapper* http_layer);
|
std::unique_ptr<LibcurlWrapper> http_layer);
|
||||||
|
|
||||||
void Init(const string& product,
|
void Init(const string& product,
|
||||||
const string& version,
|
const string& version,
|
||||||
|
@ -78,7 +78,7 @@ class GoogleCrashdumpUploader {
|
||||||
const string& crash_server,
|
const string& crash_server,
|
||||||
const string& proxy_host,
|
const string& proxy_host,
|
||||||
const string& proxy_userpassword,
|
const string& proxy_userpassword,
|
||||||
LibcurlWrapper* http_layer);
|
std::unique_ptr<LibcurlWrapper> http_layer);
|
||||||
bool Upload(int* http_status_code,
|
bool Upload(int* http_status_code,
|
||||||
string* http_response_header,
|
string* http_response_header,
|
||||||
string* http_response_body);
|
string* http_response_body);
|
||||||
|
@ -86,7 +86,7 @@ class GoogleCrashdumpUploader {
|
||||||
private:
|
private:
|
||||||
bool CheckRequiredParametersArePresent();
|
bool CheckRequiredParametersArePresent();
|
||||||
|
|
||||||
scoped_ptr<LibcurlWrapper> http_layer_;
|
std::unique_ptr<LibcurlWrapper> http_layer_;
|
||||||
string product_;
|
string product_;
|
||||||
string version_;
|
string version_;
|
||||||
string guid_;
|
string guid_;
|
||||||
|
|
|
@ -59,21 +59,12 @@ class GoogleCrashdumpUploaderTest : public ::testing::Test {
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) {
|
TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) {
|
||||||
MockLibcurlWrapper m;
|
std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()};
|
||||||
EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(false));
|
EXPECT_CALL(*m, Init()).Times(1).WillOnce(Return(false));
|
||||||
GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
|
GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "",
|
||||||
"1.0",
|
"test@test.com", "none", "/tmp/foo.dmp",
|
||||||
"AAA-BBB",
|
"http://foo.com", "", "", std::move(m));
|
||||||
"",
|
ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL));
|
||||||
"",
|
|
||||||
"test@test.com",
|
|
||||||
"none",
|
|
||||||
"/tmp/foo.dmp",
|
|
||||||
"http://foo.com",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
&m);
|
|
||||||
ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) {
|
TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) {
|
||||||
|
@ -83,44 +74,27 @@ TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) {
|
||||||
ASSERT_NE(fd, -1);
|
ASSERT_NE(fd, -1);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
MockLibcurlWrapper m;
|
std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()};
|
||||||
EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true));
|
EXPECT_CALL(*m, Init()).Times(1).WillOnce(Return(true));
|
||||||
EXPECT_CALL(m, AddFile(tempfn, _)).WillOnce(Return(true));
|
EXPECT_CALL(*m, AddFile(tempfn, _)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(m,
|
EXPECT_CALL(*m, SendRequest("http://foo.com", _, _, _, _))
|
||||||
SendRequest("http://foo.com",_,_,_,_)).Times(1).WillOnce(Return(true));
|
.Times(1)
|
||||||
GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
|
.WillOnce(Return(true));
|
||||||
"1.0",
|
GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "",
|
||||||
"AAA-BBB",
|
"test@test.com", "none", tempfn,
|
||||||
"",
|
"http://foo.com", "", "", std::move(m));
|
||||||
"",
|
ASSERT_TRUE(uploader.Upload(NULL, NULL, NULL));
|
||||||
"test@test.com",
|
|
||||||
"none",
|
|
||||||
tempfn,
|
|
||||||
"http://foo.com",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
&m);
|
|
||||||
ASSERT_TRUE(uploader->Upload(NULL, NULL, NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) {
|
TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) {
|
||||||
MockLibcurlWrapper m;
|
std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()};
|
||||||
EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true));
|
EXPECT_CALL(*m, Init()).Times(1).WillOnce(Return(true));
|
||||||
EXPECT_CALL(m, SendRequest(_,_,_,_,_)).Times(0);
|
EXPECT_CALL(*m, SendRequest(_,_,_,_,_)).Times(0);
|
||||||
GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
|
GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "",
|
||||||
"1.0",
|
"test@test.com", "none", "/tmp/foo.dmp",
|
||||||
"AAA-BBB",
|
"http://foo.com", "", "", std::move(m));
|
||||||
"",
|
ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL));
|
||||||
"",
|
|
||||||
"test@test.com",
|
|
||||||
"none",
|
|
||||||
"/tmp/foo.dmp",
|
|
||||||
"http://foo.com",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
&m);
|
|
||||||
ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) {
|
TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) {
|
||||||
|
|
Loading…
Reference in a new issue