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();
|
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().
|
// TODO(scottmg): Need to be ported to MultiprocessExec and not rely on fork().
|
||||||
#if !defined(OS_FUCHSIA)
|
#if !defined(OS_FUCHSIA)
|
||||||
|
|
||||||
@ -183,102 +358,6 @@ bool ReadCStringSizeLimited(const ProcessMemory& memory,
|
|||||||
FromPointerCast<VMAddress>(pointer), size, result);
|
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 {
|
class ReadUnmappedTest : public TargetProcessTest {
|
||||||
public:
|
public:
|
||||||
ReadUnmappedTest()
|
ReadUnmappedTest()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user