OLD | NEW |
---|---|
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 16 matching lines...) Expand all Loading... | |
27 EXPECT_LT(rva, file_contents.size()); | 27 EXPECT_LT(rva, file_contents.size()); |
28 return nullptr; | 28 return nullptr; |
29 } | 29 } |
30 | 30 |
31 return &file_contents[rva]; | 31 return &file_contents[rva]; |
32 } | 32 } |
33 | 33 |
34 const void* MinidumpWritableAtLocationDescriptorInternal( | 34 const void* MinidumpWritableAtLocationDescriptorInternal( |
35 const std::string& file_contents, | 35 const std::string& file_contents, |
36 const MINIDUMP_LOCATION_DESCRIPTOR& location, | 36 const MINIDUMP_LOCATION_DESCRIPTOR& location, |
37 size_t expected_minimum_size) { | 37 size_t expected_size, |
38 bool allow_oversized_data) { | |
38 if (location.DataSize == 0) { | 39 if (location.DataSize == 0) { |
39 EXPECT_EQ(0u, location.Rva); | 40 EXPECT_EQ(0u, location.Rva); |
40 return nullptr; | 41 return nullptr; |
41 } else if (location.DataSize < expected_minimum_size) { | 42 } |
42 EXPECT_GE(location.DataSize, expected_minimum_size); | 43 |
44 if (allow_oversized_data) { | |
45 if (location.DataSize < expected_size) { | |
46 EXPECT_GE(location.DataSize, expected_size); | |
47 return nullptr; | |
48 } | |
49 } else if (location.DataSize != expected_size) { | |
50 EXPECT_EQ(expected_size, location.DataSize); | |
43 return nullptr; | 51 return nullptr; |
44 } | 52 } |
45 | 53 |
46 RVA end = location.Rva + location.DataSize; | 54 RVA end = location.Rva + location.DataSize; |
47 if (end > file_contents.size()) { | 55 if (end > file_contents.size()) { |
48 EXPECT_LE(end, file_contents.size()); | 56 EXPECT_LE(end, file_contents.size()); |
49 return nullptr; | 57 return nullptr; |
50 } | 58 } |
51 | 59 |
52 const void* rv = MinidumpWritableAtRVAInternal(file_contents, location.Rva); | 60 const void* rv = MinidumpWritableAtRVAInternal(file_contents, location.Rva); |
53 | 61 |
54 return rv; | 62 return rv; |
55 } | 63 } |
56 | 64 |
65 template <> | |
66 const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>( | |
67 const std::string& file_contents, | |
68 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
69 const IMAGE_DEBUG_MISC* misc = | |
70 TMinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(file_contents, | |
71 location); | |
72 if (!misc) { | |
73 return nullptr; | |
74 } | |
75 | |
76 if (misc->DataType != IMAGE_DEBUG_MISC_EXENAME) { | |
77 EXPECT_EQ(static_cast<uint32_t>(IMAGE_DEBUG_MISC_EXENAME), misc->DataType); | |
78 return nullptr; | |
79 } | |
80 | |
81 if (misc->Length != location.DataSize) { | |
82 EXPECT_EQ(location.DataSize, misc->Length); | |
83 return nullptr; | |
84 } | |
85 | |
86 if (misc->Unicode == 0) { | |
87 size_t string_length = misc->Length - offsetof(IMAGE_DEBUG_MISC, Data) - 1; | |
88 if (misc->Data[string_length] != '\0') { | |
89 EXPECT_EQ('\0', misc->Data[string_length]); | |
90 return nullptr; | |
91 } | |
92 } else if (misc->Unicode == 1) { | |
93 if (misc->Length % 2 != 0) { | |
Robert Sesek
2014/10/22 21:57:52
Would be helpful to have a comment that Unicode in
| |
94 EXPECT_EQ(0u, misc->Length % 2); | |
95 return nullptr; | |
96 } | |
97 | |
98 size_t string_length = | |
99 (misc->Length - offsetof(IMAGE_DEBUG_MISC, Data)) / 2 - 1; | |
100 const uint16_t* data16 = reinterpret_cast<const uint16_t*>(misc->Data); | |
101 if (data16[string_length] != '\0') { | |
102 EXPECT_EQ('\0', data16[string_length]); | |
103 return nullptr; | |
104 } | |
105 } else { | |
106 ADD_FAILURE() << "misc->Unicode " << misc->Unicode; | |
107 return nullptr; | |
108 } | |
109 | |
110 return misc; | |
111 } | |
112 | |
113 template <> | |
114 const MINIDUMP_HEADER* MinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>( | |
115 const std::string& file_contents, | |
116 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
117 const MINIDUMP_HEADER* header = | |
118 TMinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(file_contents, | |
119 location); | |
120 if (!header) { | |
121 return nullptr; | |
122 } | |
123 | |
124 if (header->Signature != MINIDUMP_SIGNATURE) { | |
125 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature); | |
126 return nullptr; | |
127 } | |
128 if (header->Version != MINIDUMP_VERSION) { | |
129 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version); | |
130 return nullptr; | |
131 } | |
132 | |
133 return header; | |
134 } | |
135 | |
136 namespace { | |
137 | |
138 struct MinidumpMemoryListTraits { | |
139 typedef MINIDUMP_MEMORY_LIST ListType; | |
140 static constexpr size_t kElementSize = sizeof(MINIDUMP_MEMORY_DESCRIPTOR); | |
141 static size_t ElementCount(const ListType* list) { | |
142 return list->NumberOfMemoryRanges; | |
143 } | |
144 }; | |
145 | |
146 struct MinidumpModuleListTraits { | |
147 typedef MINIDUMP_MODULE_LIST ListType; | |
148 static constexpr size_t kElementSize = sizeof(MINIDUMP_MODULE); | |
149 static size_t ElementCount(const ListType* list) { | |
150 return list->NumberOfModules; | |
151 } | |
152 }; | |
153 | |
154 struct MinidumpThreadListTraits { | |
155 typedef MINIDUMP_THREAD_LIST ListType; | |
156 static constexpr size_t kElementSize = sizeof(MINIDUMP_THREAD); | |
157 static size_t ElementCount(const ListType* list) { | |
158 return list->NumberOfThreads; | |
159 } | |
160 }; | |
161 | |
162 struct MinidumpSimpleStringDictionaryListTraits { | |
163 typedef MinidumpSimpleStringDictionary ListType; | |
164 static constexpr size_t kElementSize = | |
165 sizeof(MinidumpSimpleStringDictionaryEntry); | |
166 static size_t ElementCount(const ListType* list) { return list->count; } | |
Robert Sesek
2014/10/22 21:57:52
nit: This is the only impl that you onelined.
| |
167 }; | |
168 | |
169 template <typename T> | |
170 const typename T::ListType* MinidumpListAtLocationDescriptor( | |
171 const std::string& file_contents, | |
172 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
173 const typename T::ListType* list = | |
174 TMinidumpWritableAtLocationDescriptor<typename T::ListType>(file_contents, | |
175 location); | |
176 if (!list) { | |
177 return nullptr; | |
178 } | |
179 | |
180 size_t expected_size = | |
181 sizeof(typename T::ListType) + T::ElementCount(list) * T::kElementSize; | |
182 if (location.DataSize != expected_size) { | |
183 EXPECT_EQ(expected_size, location.DataSize); | |
184 return nullptr; | |
185 } | |
186 | |
187 return list; | |
188 } | |
189 | |
190 } // namespace | |
191 | |
192 template <> | |
193 const MINIDUMP_MEMORY_LIST* MinidumpWritableAtLocationDescriptor< | |
194 MINIDUMP_MEMORY_LIST>(const std::string& file_contents, | |
195 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
196 return MinidumpListAtLocationDescriptor<MinidumpMemoryListTraits>( | |
197 file_contents, location); | |
198 } | |
199 | |
200 template <> | |
201 const MINIDUMP_MODULE_LIST* MinidumpWritableAtLocationDescriptor< | |
202 MINIDUMP_MODULE_LIST>(const std::string& file_contents, | |
203 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
204 return MinidumpListAtLocationDescriptor<MinidumpModuleListTraits>( | |
205 file_contents, location); | |
206 } | |
207 | |
208 template <> | |
209 const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor< | |
210 MINIDUMP_THREAD_LIST>(const std::string& file_contents, | |
211 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
212 return MinidumpListAtLocationDescriptor<MinidumpThreadListTraits>( | |
213 file_contents, location); | |
214 } | |
215 | |
216 template <> | |
217 const MinidumpSimpleStringDictionary* | |
218 MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>( | |
219 const std::string& file_contents, | |
220 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
221 return MinidumpListAtLocationDescriptor< | |
222 MinidumpSimpleStringDictionaryListTraits>(file_contents, location); | |
223 } | |
224 | |
225 namespace { | |
226 | |
227 template <typename T> | |
228 const T* MinidumpCVPDBAtLocationDescriptor( | |
229 const std::string& file_contents, | |
230 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
231 const T* cv_pdb = | |
232 TMinidumpWritableAtLocationDescriptor<T>(file_contents, location); | |
233 if (!cv_pdb) { | |
234 return nullptr; | |
235 } | |
236 | |
237 if (cv_pdb->signature != T::kSignature) { | |
238 EXPECT_EQ(T::kSignature, cv_pdb->signature); | |
239 return nullptr; | |
240 } | |
241 | |
242 size_t string_length = location.DataSize - offsetof(T, pdb_name) - 1; | |
243 if (cv_pdb->pdb_name[string_length] != '\0') { | |
244 EXPECT_EQ('\0', cv_pdb->pdb_name[string_length]); | |
245 return nullptr; | |
246 } | |
247 | |
248 return cv_pdb; | |
249 } | |
250 | |
251 } // namespace | |
252 | |
253 template <> | |
254 const MinidumpModuleCodeViewRecordPDB20* | |
255 MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>( | |
256 const std::string& file_contents, | |
257 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
258 return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>( | |
259 file_contents, location); | |
260 } | |
261 | |
262 template <> | |
263 const MinidumpModuleCodeViewRecordPDB70* | |
264 MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>( | |
265 const std::string& file_contents, | |
266 const MINIDUMP_LOCATION_DESCRIPTOR& location) { | |
267 return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>( | |
268 file_contents, location); | |
269 } | |
270 | |
57 } // namespace test | 271 } // namespace test |
58 } // namespace crashpad | 272 } // namespace crashpad |
OLD | NEW |