mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-25 22:30:49 +08:00
940e8a3445
CrashpadInfo::AddUserDataMinidumpStream() and UpdateUserDataMinidumpStream() allocate memory for the newly added streams. This change makes the CrashpadInfo test free that allocated memory to prevent memory leaks from these tests. This is intended to fix the ASAN failures seen on crrev.com/c/5285881: https://ci.chromium.org/ui/p/chromium/builders/try/linux_chromium_asan_rel_ng/1839072/overview Bug: crashpad:474 Change-Id: I6e030291594d22e316942a58805a177ce448053b Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/5292137 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Jesse McKenna <jessemckenna@google.com>
143 lines
5.2 KiB
C++
143 lines
5.2 KiB
C++
// Copyright 2024 The Crashpad Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "client/crashpad_info.h"
|
|
|
|
#include <string>
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace crashpad {
|
|
namespace test {
|
|
namespace {
|
|
|
|
constexpr uint32_t kTestStreamType = 0x33333;
|
|
|
|
class CrashpadInfoTest : public testing::Test {
|
|
protected:
|
|
CrashpadInfo& crashpad_info() { return crashpad_info_; }
|
|
|
|
// Returns the current head of the list of streams in `crashpad_info_`. Note
|
|
// that the returned pointer is invalidated if a stream is added or updated.
|
|
internal::UserDataMinidumpStreamListEntry* GetCurrentHead() {
|
|
return crashpad_info().GetUserDataMinidumpStreamHeadForTesting();
|
|
}
|
|
|
|
// Returns a pointer to the next node in the list after the given `node`.
|
|
internal::UserDataMinidumpStreamListEntry* GetNext(
|
|
internal::UserDataMinidumpStreamListEntry* node) {
|
|
return reinterpret_cast<internal::UserDataMinidumpStreamListEntry*>(
|
|
node->next);
|
|
}
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_head() {
|
|
return initial_head_;
|
|
}
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_tail() {
|
|
return initial_tail_;
|
|
}
|
|
|
|
private:
|
|
void SetUp() override {
|
|
ASSERT_EQ(nullptr, GetCurrentHead());
|
|
|
|
// Create a simple test list with the structure
|
|
// `initial_head_` -> `initial_tail_`.
|
|
initial_tail_ = AddStream(0x11111, kInitialTailData);
|
|
initial_head_ = AddStream(0x22222, kInitialHeadData);
|
|
|
|
// Validate the list's contents.
|
|
auto current = GetCurrentHead();
|
|
ASSERT_EQ(initial_head_, current);
|
|
ASSERT_EQ(kInitialHeadData, reinterpret_cast<char*>(current->base_address));
|
|
current = GetNext(current);
|
|
ASSERT_EQ(initial_tail_, current);
|
|
ASSERT_EQ(nullptr, GetNext(current));
|
|
}
|
|
|
|
void TearDown() override {
|
|
// Free the list. The list lives until process exit in production, but must
|
|
// be freed in tests as multiple tests run in the same process.
|
|
auto current = GetCurrentHead();
|
|
while (current) {
|
|
auto next = GetNext(current);
|
|
delete current;
|
|
current = next;
|
|
}
|
|
}
|
|
|
|
internal::UserDataMinidumpStreamListEntry* AddStream(uint32_t stream_type,
|
|
const char* data) {
|
|
return reinterpret_cast<internal::UserDataMinidumpStreamListEntry*>(
|
|
crashpad_info().AddUserDataMinidumpStream(
|
|
stream_type, data, strlen(data)));
|
|
}
|
|
|
|
CrashpadInfo crashpad_info_;
|
|
|
|
static constexpr char kInitialHeadData[] = "head";
|
|
static constexpr char kInitialTailData[] = "tail";
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_head_ = nullptr;
|
|
internal::UserDataMinidumpStreamListEntry* initial_tail_ = nullptr;
|
|
};
|
|
|
|
// Tests that updating the head of the list updates the head pointer, the new
|
|
// head contains the updated data, and the updated node points to the next node.
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamHead) {
|
|
const std::string new_data = "this is a new string";
|
|
const auto new_entry = crashpad_info().UpdateUserDataMinidumpStream(
|
|
initial_head(), kTestStreamType, new_data.data(), new_data.size());
|
|
const auto head = GetCurrentHead();
|
|
EXPECT_EQ(new_entry, head);
|
|
EXPECT_EQ(new_data.data(), reinterpret_cast<char*>(head->base_address));
|
|
EXPECT_EQ(new_data.size(), head->size);
|
|
EXPECT_EQ(kTestStreamType, head->stream_type);
|
|
EXPECT_EQ(initial_tail(), GetNext(head));
|
|
}
|
|
|
|
// Tests that updating the tail of the list results in a tail pointing to
|
|
// nullptr, and that the node before the updated node points to it.
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamTail) {
|
|
const std::string new_data = "new";
|
|
const auto new_entry = crashpad_info().UpdateUserDataMinidumpStream(
|
|
initial_tail(), kTestStreamType, new_data.data(), new_data.size());
|
|
const auto tail = GetNext(GetCurrentHead());
|
|
EXPECT_EQ(new_entry, tail);
|
|
EXPECT_EQ(nullptr, GetNext(tail));
|
|
}
|
|
|
|
// Tests that the handle returned from updating an entry is usable for updating
|
|
// the entry again.
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamMultipleTimes) {
|
|
// Update the entry at the head; the updated entry should become the new head.
|
|
const std::string new_data = "new";
|
|
const auto new_entry_1 = crashpad_info().UpdateUserDataMinidumpStream(
|
|
initial_head(), kTestStreamType, new_data.data(), new_data.size());
|
|
EXPECT_EQ(new_entry_1, GetCurrentHead());
|
|
|
|
// Update the updated entry again; another new entry should replace it as
|
|
// head.
|
|
const auto new_entry_2 = crashpad_info().UpdateUserDataMinidumpStream(
|
|
new_entry_1, kTestStreamType, new_data.data(), new_data.size());
|
|
EXPECT_NE(new_entry_1, new_entry_2);
|
|
EXPECT_EQ(new_entry_2, GetCurrentHead());
|
|
EXPECT_EQ(initial_tail(), GetNext(GetCurrentHead()));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace test
|
|
} // namespace crashpad
|