win: Add UUID::InitializeFromSystemUUID().

The new call is also used in
CrashReportDatabaseWin::PrepareNewCrashReport(). Previously, that method
used the UUID::InitializeFromBytes() constructor. That actually caused
various fields of the UUID to be byte-swapped so that the ::UUID and
crashpad::UUID would be different UUIDs. Although a UUID is mostly
random, the version field in data_3 is used as a namespace and should be
4 for random UUIDs, and this was not the case under swapping.

TEST=crashpad_util_test UUID.FromSystem
BUG=crashpad:1
R=scottmg@chromium.org

Review URL: https://codereview.chromium.org/1004913004
This commit is contained in:
Mark Mentovai 2015-03-13 13:53:38 -04:00
parent 6bf80c3e48
commit e7b80a52f5
5 changed files with 52 additions and 5 deletions

View File

@ -576,12 +576,9 @@ OperationStatus CrashReportDatabaseWin::PrepareNewCrashReport(
::UUID system_uuid;
if (UuidCreate(&system_uuid) != RPC_S_OK)
return kFileSystemError;
static_assert(sizeof(system_uuid) == 16, "unexpected system uuid size");
static_assert(offsetof(::UUID, Data1) == 0, "unexpected uuid layout");
scoped_ptr<NewReport> new_report(new NewReport());
new_report->uuid.InitializeFromBytes(
reinterpret_cast<const uint8_t*>(&system_uuid.Data1));
new_report->uuid.InitializeFromSystemUUID(&system_uuid);
new_report->path = base_dir_.Append(kReportsDirectory)
.Append(new_report->uuid.ToString16() + L"." +
kCrashReportFileExtension);

View File

@ -88,6 +88,16 @@ bool UUID::InitializeFromString(const base::StringPiece& string) {
return true;
}
#if defined(OS_WIN)
void UUID::InitializeFromSystemUUID(const ::UUID* system_uuid) {
static_assert(sizeof(::UUID) == sizeof(UUID),
"unexpected system uuid size");
static_assert(offsetof(::UUID, Data1) == offsetof(UUID, data_1),
"unexpected system uuid layout");
memcpy(this, system_uuid, sizeof(::UUID));
}
#endif // OS_WIN
std::string UUID::ToString() const {
return base::StringPrintf("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
data_1,

View File

@ -23,6 +23,10 @@
#include "base/strings/string_piece.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include <rpc.h>
#endif
namespace crashpad {
//! \brief A universally unique identifier (%UUID).
@ -63,12 +67,19 @@ struct UUID {
//! parsed, with the object state untouched.
bool InitializeFromString(const base::StringPiece& string);
#if defined(OS_WIN) || DOXYGEN
//! \brief Initializes the %UUID from a system `UUID` or `GUID` structure.
//!
//! \param[in] system_uuid A system `UUID` or `GUID` structure.
void InitializeFromSystemUUID(const ::UUID* system_uuid);
#endif // OS_WIN
//! \brief Formats the %UUID per RFC 4122 §3.
//!
//! \return A string of the form `"00112233-4455-6677-8899-aabbccddeeff"`.
std::string ToString() const;
#if defined(OS_WIN)
#if defined(OS_WIN) || DOXYGEN
//! \brief The same as ToString, but returned as a string16.
base::string16 ToString16() const;
#endif // OS_WIN

View File

@ -20,6 +20,7 @@
#include "base/basictypes.h"
#include "base/format_macros.h"
#include "base/scoped_generic.h"
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
@ -204,6 +205,33 @@ TEST(UUID, FromString) {
EXPECT_EQ("5762c15d-50b5-4171-a2e9-7429c9ec6cab", uuid.ToString());
}
#if defined(OS_WIN)
TEST(UUID, FromSystem) {
::GUID system_uuid;
ASSERT_EQ(RPC_S_OK, UuidCreate(&system_uuid));
UUID uuid;
uuid.InitializeFromSystemUUID(&system_uuid);
RPC_WSTR system_string;
ASSERT_EQ(RPC_S_OK, UuidToString(&system_uuid, &system_string));
struct ScopedRpcStringFreeTraits {
static RPC_WSTR* InvalidValue() { return nullptr; }
static void Free(RPC_WSTR* rpc_string) {
EXPECT_EQ(RPC_S_OK, RpcStringFree(rpc_string));
}
};
using ScopedRpcString =
base::ScopedGeneric<RPC_WSTR*, ScopedRpcStringFreeTraits>;
ScopedRpcString scoped_system_string(&system_string);
EXPECT_EQ(reinterpret_cast<wchar_t*>(system_string), uuid.ToString16());
}
#endif // OS_WIN
} // namespace
} // namespace test
} // namespace crashpad

View File

@ -208,6 +208,7 @@
['OS=="win"', {
'link_settings': {
'libraries': [
'-lrpcrt4.lib',
'-lwinhttp.lib',
],
},