mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-15 01:57:58 +08:00
Rework ReadCString[SizeLimited](Self|Forked) to not use fork()
Instead of using pointers shared between the parent/child due to fork, explicitly builds and passes them between processes. This is unfortunately a bit more verbose, but seems like it tests functionality a little better, and is required to have the test work on Fuchsia. Also renames the ...Forked to ...Child to be correct after the change from Multiprocess to MultiprocessExec. Bug: crashpad:196, crashpad:215 Change-Id: I610a7f1e35b6513805c27d9e610f7a9b9820cabc Reviewed-on: https://chromium-review.googlesource.com/892286 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
ec71b63d6f
commit
693ff6d550
@ -147,6 +147,181 @@ TEST(ProcessMemory, ReadChild) {
|
||||
test.RunAgainstChild();
|
||||
}
|
||||
|
||||
constexpr char kConstCharEmpty[] = "";
|
||||
constexpr char kConstCharShort[] = "A short const char[]";
|
||||
|
||||
#define SHORT_LOCAL_STRING "A short local variable char[]"
|
||||
|
||||
std::string MakeLongString() {
|
||||
std::string long_string;
|
||||
const size_t kStringLongSize = 4 * getpagesize();
|
||||
for (size_t index = 0; index < kStringLongSize; ++index) {
|
||||
long_string.push_back((index % 255) + 1);
|
||||
}
|
||||
EXPECT_EQ(long_string.size(), kStringLongSize);
|
||||
return long_string;
|
||||
}
|
||||
|
||||
void DoChildCStringReadTestSetup(const char** const_empty,
|
||||
const char** const_short,
|
||||
const char** local_empty,
|
||||
const char** local_short,
|
||||
std::string* long_string) {
|
||||
*const_empty = kConstCharEmpty;
|
||||
*const_short = kConstCharShort;
|
||||
*local_empty = "";
|
||||
*local_short = SHORT_LOCAL_STRING;
|
||||
*long_string = MakeLongString();
|
||||
}
|
||||
|
||||
CRASHPAD_CHILD_TEST_MAIN(ReadCStringTestChild) {
|
||||
const char* const_empty;
|
||||
const char* const_short;
|
||||
const char* local_empty;
|
||||
const char* local_short;
|
||||
std::string long_string;
|
||||
DoChildCStringReadTestSetup(
|
||||
&const_empty, &const_short, &local_empty, &local_short, &long_string);
|
||||
const auto write_address = [](const char* p) {
|
||||
VMAddress address = FromPointerCast<VMAddress>(p);
|
||||
CheckedWriteFile(StdioFileHandle(StdioStream::kStandardOutput),
|
||||
&address,
|
||||
sizeof(address));
|
||||
};
|
||||
write_address(const_empty);
|
||||
write_address(const_short);
|
||||
write_address(local_empty);
|
||||
write_address(local_short);
|
||||
write_address(long_string.c_str());
|
||||
CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
|
||||
return 0;
|
||||
}
|
||||
|
||||
class ReadCStringTest : public MultiprocessExec {
|
||||
public:
|
||||
ReadCStringTest(bool limit_size)
|
||||
: MultiprocessExec(), limit_size_(limit_size) {
|
||||
SetChildTestMainFunction("ReadCStringTestChild");
|
||||
}
|
||||
|
||||
void RunAgainstSelf() {
|
||||
const char* const_empty;
|
||||
const char* const_short;
|
||||
const char* local_empty;
|
||||
const char* local_short;
|
||||
std::string long_string;
|
||||
DoChildCStringReadTestSetup(
|
||||
&const_empty, &const_short, &local_empty, &local_short, &long_string);
|
||||
DoTest(GetSelfProcess(),
|
||||
FromPointerCast<VMAddress>(const_empty),
|
||||
FromPointerCast<VMAddress>(const_short),
|
||||
FromPointerCast<VMAddress>(local_empty),
|
||||
FromPointerCast<VMAddress>(local_short),
|
||||
FromPointerCast<VMAddress>(long_string.c_str()));
|
||||
}
|
||||
void RunAgainstChild() { Run(); }
|
||||
|
||||
private:
|
||||
void MultiprocessParent() override {
|
||||
#define DECLARE_AND_READ_ADDRESS(name) \
|
||||
VMAddress name; \
|
||||
ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(), &name, sizeof(name)));
|
||||
DECLARE_AND_READ_ADDRESS(const_empty_address);
|
||||
DECLARE_AND_READ_ADDRESS(const_short_address);
|
||||
DECLARE_AND_READ_ADDRESS(local_empty_address);
|
||||
DECLARE_AND_READ_ADDRESS(local_short_address);
|
||||
DECLARE_AND_READ_ADDRESS(long_string_address);
|
||||
#undef DECLARE_AND_READ_ADDRESS
|
||||
|
||||
DoTest(ChildProcess(),
|
||||
const_empty_address,
|
||||
const_short_address,
|
||||
local_empty_address,
|
||||
local_short_address,
|
||||
long_string_address);
|
||||
}
|
||||
|
||||
void DoTest(ProcessType process,
|
||||
VMAddress const_empty_address,
|
||||
VMAddress const_short_address,
|
||||
VMAddress local_empty_address,
|
||||
VMAddress local_short_address,
|
||||
VMAddress long_string_address) {
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
|
||||
std::string result;
|
||||
|
||||
if (limit_size_) {
|
||||
ASSERT_TRUE(memory.ReadCStringSizeLimited(
|
||||
const_empty_address, arraysize(kConstCharEmpty), &result));
|
||||
EXPECT_EQ(result, kConstCharEmpty);
|
||||
|
||||
ASSERT_TRUE(memory.ReadCStringSizeLimited(
|
||||
const_short_address, arraysize(kConstCharShort), &result));
|
||||
EXPECT_EQ(result, kConstCharShort);
|
||||
EXPECT_FALSE(memory.ReadCStringSizeLimited(
|
||||
const_short_address, arraysize(kConstCharShort) - 1, &result));
|
||||
|
||||
ASSERT_TRUE(
|
||||
memory.ReadCStringSizeLimited(local_empty_address, 1, &result));
|
||||
EXPECT_EQ(result, "");
|
||||
|
||||
ASSERT_TRUE(memory.ReadCStringSizeLimited(
|
||||
local_short_address, strlen(SHORT_LOCAL_STRING) + 1, &result));
|
||||
EXPECT_EQ(result, SHORT_LOCAL_STRING);
|
||||
EXPECT_FALSE(memory.ReadCStringSizeLimited(
|
||||
local_short_address, strlen(SHORT_LOCAL_STRING), &result));
|
||||
|
||||
std::string long_string_for_comparison = MakeLongString();
|
||||
ASSERT_TRUE(memory.ReadCStringSizeLimited(
|
||||
long_string_address, long_string_for_comparison.size() + 1, &result));
|
||||
EXPECT_EQ(result, long_string_for_comparison);
|
||||
EXPECT_FALSE(memory.ReadCStringSizeLimited(
|
||||
long_string_address, long_string_for_comparison.size(), &result));
|
||||
} else {
|
||||
ASSERT_TRUE(memory.ReadCString(const_empty_address, &result));
|
||||
EXPECT_EQ(result, kConstCharEmpty);
|
||||
|
||||
ASSERT_TRUE(memory.ReadCString(const_short_address, &result));
|
||||
EXPECT_EQ(result, kConstCharShort);
|
||||
|
||||
ASSERT_TRUE(memory.ReadCString(local_empty_address, &result));
|
||||
EXPECT_EQ(result, "");
|
||||
|
||||
ASSERT_TRUE(memory.ReadCString(local_short_address, &result));
|
||||
EXPECT_EQ(result, SHORT_LOCAL_STRING);
|
||||
|
||||
ASSERT_TRUE(memory.ReadCString(long_string_address, &result));
|
||||
EXPECT_EQ(result, MakeLongString());
|
||||
}
|
||||
}
|
||||
|
||||
const bool limit_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ReadCStringTest);
|
||||
};
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSelf) {
|
||||
ReadCStringTest test(/* limit_size= */ false);
|
||||
test.RunAgainstSelf();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringChild) {
|
||||
ReadCStringTest test(/* limit_size= */ false);
|
||||
test.RunAgainstChild();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSizeLimitedSelf) {
|
||||
ReadCStringTest test(/* limit_size= */ true);
|
||||
test.RunAgainstSelf();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSizeLimitedChild) {
|
||||
ReadCStringTest test(/* limit_size= */ true);
|
||||
test.RunAgainstChild();
|
||||
}
|
||||
|
||||
// TODO(scottmg): Need to be ported to MultiprocessExec and not rely on fork().
|
||||
#if !defined(OS_FUCHSIA)
|
||||
|
||||
@ -183,102 +358,6 @@ bool ReadCStringSizeLimited(const ProcessMemory& memory,
|
||||
FromPointerCast<VMAddress>(pointer), size, result);
|
||||
}
|
||||
|
||||
constexpr char kConstCharEmpty[] = "";
|
||||
constexpr char kConstCharShort[] = "A short const char[]";
|
||||
|
||||
class ReadCStringTest : public TargetProcessTest {
|
||||
public:
|
||||
ReadCStringTest(bool limit_size)
|
||||
: TargetProcessTest(),
|
||||
member_char_empty_(""),
|
||||
member_char_short_("A short member char[]"),
|
||||
limit_size_(limit_size) {
|
||||
const size_t kStringLongSize = 4 * getpagesize();
|
||||
for (size_t index = 0; index < kStringLongSize; ++index) {
|
||||
string_long_.push_back((index % 255) + 1);
|
||||
}
|
||||
EXPECT_EQ(string_long_.size(), kStringLongSize);
|
||||
}
|
||||
|
||||
private:
|
||||
void DoTest(pid_t pid) override {
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(pid));
|
||||
|
||||
std::string result;
|
||||
|
||||
if (limit_size_) {
|
||||
ASSERT_TRUE(ReadCStringSizeLimited(
|
||||
memory, kConstCharEmpty, arraysize(kConstCharEmpty), &result));
|
||||
EXPECT_EQ(result, kConstCharEmpty);
|
||||
|
||||
ASSERT_TRUE(ReadCStringSizeLimited(
|
||||
memory, kConstCharShort, arraysize(kConstCharShort), &result));
|
||||
EXPECT_EQ(result, kConstCharShort);
|
||||
EXPECT_FALSE(ReadCStringSizeLimited(
|
||||
memory, kConstCharShort, arraysize(kConstCharShort) - 1, &result));
|
||||
|
||||
ASSERT_TRUE(ReadCStringSizeLimited(
|
||||
memory, member_char_empty_, strlen(member_char_empty_) + 1, &result));
|
||||
EXPECT_EQ(result, member_char_empty_);
|
||||
|
||||
ASSERT_TRUE(ReadCStringSizeLimited(
|
||||
memory, member_char_short_, strlen(member_char_short_) + 1, &result));
|
||||
EXPECT_EQ(result, member_char_short_);
|
||||
EXPECT_FALSE(ReadCStringSizeLimited(
|
||||
memory, member_char_short_, strlen(member_char_short_), &result));
|
||||
|
||||
ASSERT_TRUE(ReadCStringSizeLimited(
|
||||
memory, string_long_.c_str(), string_long_.size() + 1, &result));
|
||||
EXPECT_EQ(result, string_long_);
|
||||
EXPECT_FALSE(ReadCStringSizeLimited(
|
||||
memory, string_long_.c_str(), string_long_.size(), &result));
|
||||
} else {
|
||||
ASSERT_TRUE(ReadCString(memory, kConstCharEmpty, &result));
|
||||
EXPECT_EQ(result, kConstCharEmpty);
|
||||
|
||||
ASSERT_TRUE(ReadCString(memory, kConstCharShort, &result));
|
||||
EXPECT_EQ(result, kConstCharShort);
|
||||
|
||||
ASSERT_TRUE(ReadCString(memory, member_char_empty_, &result));
|
||||
EXPECT_EQ(result, member_char_empty_);
|
||||
|
||||
ASSERT_TRUE(ReadCString(memory, member_char_short_, &result));
|
||||
EXPECT_EQ(result, member_char_short_);
|
||||
|
||||
ASSERT_TRUE(ReadCString(memory, string_long_.c_str(), &result));
|
||||
EXPECT_EQ(result, string_long_);
|
||||
}
|
||||
}
|
||||
|
||||
std::string string_long_;
|
||||
const char* member_char_empty_;
|
||||
const char* member_char_short_;
|
||||
const bool limit_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ReadCStringTest);
|
||||
};
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSelf) {
|
||||
ReadCStringTest test(/* limit_size= */ false);
|
||||
test.RunAgainstSelf();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringForked) {
|
||||
ReadCStringTest test(/* limit_size= */ false);
|
||||
test.RunAgainstForked();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSizeLimitedSelf) {
|
||||
ReadCStringTest test(/* limit_size= */ true);
|
||||
test.RunAgainstSelf();
|
||||
}
|
||||
|
||||
TEST(ProcessMemory, ReadCStringSizeLimitedForked) {
|
||||
ReadCStringTest test(/* limit_size= */ true);
|
||||
test.RunAgainstForked();
|
||||
}
|
||||
|
||||
class ReadUnmappedTest : public TargetProcessTest {
|
||||
public:
|
||||
ReadUnmappedTest()
|
||||
|
Loading…
x
Reference in New Issue
Block a user