Chromium Code Reviews| 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 |