1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #if !defined(__STDC_FORMAT_MACROS)
16 #define __STDC_FORMAT_MACROS
17 #endif
18
19 #include "util/misc/uuid.h"
20
21 #include <inttypes.h>
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <type_traits>
27
28 #include "base/rand_util.h"
29 #include "base/strings/stringprintf.h"
30 #include "base/strings/utf_string_conversions.h"
31 #include "base/sys_byteorder.h"
32
33 #if defined(OS_APPLE)
34 #include <uuid/uuid.h>
35 #endif // OS_APPLE
36
37 namespace crashpad {
38
39 static_assert(sizeof(UUID) == 16, "UUID must be 16 bytes");
40 static_assert(std::is_pod<UUID>::value, "UUID must be POD");
41
operator ==(const UUID & that) const42 bool UUID::operator==(const UUID& that) const {
43 return memcmp(this, &that, sizeof(*this)) == 0;
44 }
45
InitializeToZero()46 void UUID::InitializeToZero() {
47 memset(this, 0, sizeof(*this));
48 }
49
InitializeFromBytes(const uint8_t * bytes)50 void UUID::InitializeFromBytes(const uint8_t* bytes) {
51 memcpy(this, bytes, sizeof(*this));
52 data_1 = base::NetToHost32(data_1);
53 data_2 = base::NetToHost16(data_2);
54 data_3 = base::NetToHost16(data_3);
55 }
56
InitializeFromString(const base::StringPiece & string)57 bool UUID::InitializeFromString(const base::StringPiece& string) {
58 if (string.length() != 36)
59 return false;
60
61 UUID temp;
62 static constexpr char kScanFormat[] =
63 "%08" SCNx32 "-%04" SCNx16 "-%04" SCNx16
64 "-%02" SCNx8 "%02" SCNx8
65 "-%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8;
66 int rv = sscanf(string.data(),
67 kScanFormat,
68 &temp.data_1,
69 &temp.data_2,
70 &temp.data_3,
71 &temp.data_4[0],
72 &temp.data_4[1],
73 &temp.data_5[0],
74 &temp.data_5[1],
75 &temp.data_5[2],
76 &temp.data_5[3],
77 &temp.data_5[4],
78 &temp.data_5[5]);
79 if (rv != 11)
80 return false;
81
82 *this = temp;
83 return true;
84 }
85
86 #if defined(OS_WIN)
InitializeFromString(const base::WStringPiece & string)87 bool UUID::InitializeFromString(const base::WStringPiece& string) {
88 return InitializeFromString(WideToUTF8(string));
89 }
90 #endif
91
InitializeWithNew()92 bool UUID::InitializeWithNew() {
93 #if defined(OS_APPLE)
94 uuid_t uuid;
95 uuid_generate(uuid);
96 InitializeFromBytes(uuid);
97 return true;
98 #elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
99 defined(OS_ANDROID) || defined(OS_FUCHSIA)
100 // Linux, Android, and Fuchsia do not provide a UUID generator in a
101 // widely-available system library. On Linux and Android, uuid_generate()
102 // from libuuid is not available everywhere.
103 // On Windows, do not use UuidCreate() to avoid a dependency on rpcrt4, so
104 // that this function is usable early in DllMain().
105 base::RandBytes(this, sizeof(*this));
106
107 // Set six bits per RFC 4122 §4.4 to identify this as a pseudo-random UUID.
108 data_3 = (4 << 12) | (data_3 & 0x0fff); // §4.1.3
109 data_4[0] = 0x80 | (data_4[0] & 0x3f); // §4.1.1
110
111 return true;
112 #else
113 #error Port.
114 #endif // OS_APPLE
115 }
116
117 #if defined(OS_WIN)
InitializeFromSystemUUID(const::UUID * system_uuid)118 void UUID::InitializeFromSystemUUID(const ::UUID* system_uuid) {
119 static_assert(sizeof(::UUID) == sizeof(UUID),
120 "unexpected system uuid size");
121 static_assert(offsetof(::UUID, Data1) == offsetof(UUID, data_1),
122 "unexpected system uuid layout");
123 memcpy(this, system_uuid, sizeof(*this));
124 }
125 #endif // OS_WIN
126
ToString() const127 std::string UUID::ToString() const {
128 return base::StringPrintf("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
129 data_1,
130 data_2,
131 data_3,
132 data_4[0],
133 data_4[1],
134 data_5[0],
135 data_5[1],
136 data_5[2],
137 data_5[3],
138 data_5[4],
139 data_5[5]);
140 }
141
142 #if defined(OS_WIN)
ToWString() const143 std::wstring UUID::ToWString() const {
144 return base::UTF8ToWide(ToString());
145 }
146 #endif // OS_WIN
147
148 } // namespace crashpad
149