1 //===- DXContainerTest.cpp - Tests for DXContainerFile --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Object/DXContainer.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/BinaryFormat/Magic.h" 12 #include "llvm/ObjectYAML/DXContainerYAML.h" 13 #include "llvm/ObjectYAML/yaml2obj.h" 14 #include "llvm/Support/MemoryBufferRef.h" 15 #include "llvm/Testing/Support/Error.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 using namespace llvm::object; 20 21 template <std::size_t X> MemoryBufferRef getMemoryBuffer(uint8_t Data[X]) { 22 StringRef Obj(reinterpret_cast<char *>(&Data[0]), X); 23 return MemoryBufferRef(Obj, ""); 24 } 25 26 TEST(DXCFile, IdentifyMagic) { 27 { 28 StringRef Buffer("DXBC"); 29 EXPECT_EQ(identify_magic(Buffer), file_magic::dxcontainer_object); 30 } 31 { 32 StringRef Buffer("DXBCBlahBlahBlah"); 33 EXPECT_EQ(identify_magic(Buffer), file_magic::dxcontainer_object); 34 } 35 } 36 37 TEST(DXCFile, ParseHeaderErrors) { 38 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43}; 39 EXPECT_THAT_EXPECTED( 40 DXContainer::create(getMemoryBuffer<4>(Buffer)), 41 FailedWithMessage("Reading structure out of file bounds")); 42 } 43 44 TEST(DXCFile, EmptyFile) { 45 EXPECT_THAT_EXPECTED( 46 DXContainer::create(MemoryBufferRef(StringRef("", 0), "")), 47 FailedWithMessage("Reading structure out of file bounds")); 48 } 49 50 TEST(DXCFile, ParseHeader) { 51 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 54 0x70, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 55 DXContainer C = 56 llvm::cantFail(DXContainer::create(getMemoryBuffer<32>(Buffer))); 57 EXPECT_TRUE(memcmp(C.getHeader().Magic, "DXBC", 4) == 0); 58 EXPECT_TRUE(memcmp(C.getHeader().FileHash.Digest, 59 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0); 60 EXPECT_EQ(C.getHeader().Version.Major, 1u); 61 EXPECT_EQ(C.getHeader().Version.Minor, 0u); 62 } 63 64 TEST(DXCFile, ParsePartMissingOffsets) { 65 uint8_t Buffer[] = { 66 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 68 0x00, 0x00, 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 69 }; 70 EXPECT_THAT_EXPECTED( 71 DXContainer::create(getMemoryBuffer<32>(Buffer)), 72 FailedWithMessage("Reading structure out of file bounds")); 73 } 74 75 TEST(DXCFile, ParsePartInvalidOffsets) { 76 // This test covers a case where the part offset is beyond the buffer size. 77 uint8_t Buffer[] = { 78 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 80 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 81 }; 82 EXPECT_THAT_EXPECTED( 83 DXContainer::create(getMemoryBuffer<36>(Buffer)), 84 FailedWithMessage("Part offset points beyond boundary of the file")); 85 } 86 87 TEST(DXCFile, ParsePartTooSmallBuffer) { 88 // This test covers a case where there is insufficent space to read a full 89 // part name, but the offset for the part is inside the buffer. 90 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 93 0x26, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 94 0x24, 0x00, 0x00, 0x00, 0x46, 0x4B}; 95 EXPECT_THAT_EXPECTED( 96 DXContainer::create(getMemoryBuffer<38>(Buffer)), 97 FailedWithMessage("File not large enough to read part name")); 98 } 99 100 TEST(DXCFile, ParsePartNoSize) { 101 // This test covers a case where the part's header is readable, but the size 102 // the part extends beyond the boundaries of the file. 103 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00, 106 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 107 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00}; 108 EXPECT_THAT_EXPECTED( 109 DXContainer::create(getMemoryBuffer<42>(Buffer)), 110 FailedWithMessage("Reading part size out of file bounds")); 111 } 112 113 TEST(DXCFile, ParseOverlappingParts) { 114 // This test covers a case where a part's offset is inside the size range 115 // covered by the previous part. 116 uint8_t Buffer[] = { 117 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 119 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 120 0x2C, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x30, 0x08, 0x00, 0x00, 0x00, 121 0x46, 0x4B, 0x45, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 122 }; 123 EXPECT_THAT_EXPECTED( 124 DXContainer::create(getMemoryBuffer<60>(Buffer)), 125 FailedWithMessage( 126 "Part offset for part 1 begins before the previous part ends")); 127 } 128 129 TEST(DXCFile, ParseEmptyParts) { 130 uint8_t Buffer[] = { 131 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 133 0x70, 0x0D, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 134 0x44, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 135 0x5C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 136 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x31, 137 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x32, 0x00, 0x00, 0x00, 0x00, 138 0x46, 0x4B, 0x45, 0x33, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x34, 139 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x35, 0x00, 0x00, 0x00, 0x00, 140 0x46, 0x4B, 0x45, 0x36, 0x00, 0x00, 0x00, 0x00, 141 }; 142 DXContainer C = 143 llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer))); 144 EXPECT_EQ(C.getHeader().PartCount, 7u); 145 146 // All the part sizes are 0, which makes a nice test of the range based for 147 int ElementsVisited = 0; 148 for (auto Part : C) { 149 EXPECT_EQ(Part.Part.Size, 0u); 150 EXPECT_EQ(Part.Data.size(), 0u); 151 ++ElementsVisited; 152 } 153 EXPECT_EQ(ElementsVisited, 7); 154 155 { 156 // These are all intended to be fake part names so that the parser doesn't 157 // try to parse the part data. 158 auto It = C.begin(); 159 EXPECT_TRUE(memcmp(It->Part.Name, "FKE0", 4) == 0); 160 ++It; 161 EXPECT_TRUE(memcmp(It->Part.Name, "FKE1", 4) == 0); 162 ++It; 163 EXPECT_TRUE(memcmp(It->Part.Name, "FKE2", 4) == 0); 164 ++It; 165 EXPECT_TRUE(memcmp(It->Part.Name, "FKE3", 4) == 0); 166 ++It; 167 EXPECT_TRUE(memcmp(It->Part.Name, "FKE4", 4) == 0); 168 ++It; 169 EXPECT_TRUE(memcmp(It->Part.Name, "FKE5", 4) == 0); 170 ++It; 171 EXPECT_TRUE(memcmp(It->Part.Name, "FKE6", 4) == 0); 172 ++It; // Don't increment past the end 173 EXPECT_TRUE(memcmp(It->Part.Name, "FKE6", 4) == 0); 174 } 175 } 176 177 // This test verify DXIL part are correctly parsed. 178 // This test is based on the binary output constructed from this yaml. 179 // --- !dxcontainer 180 // Header: 181 // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 182 // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 183 // Version: 184 // Major: 1 185 // Minor: 0 186 // PartCount: 1 187 // Parts: 188 // - Name: DXIL 189 // Size: 28 190 // Program: 191 // MajorVersion: 6 192 // MinorVersion: 5 193 // ShaderKind: 5 194 // Size: 8 195 // DXILMajorVersion: 1 196 // DXILMinorVersion: 5 197 // DXILSize: 4 198 // DXIL: [ 0x42, 0x43, 0xC0, 0xDE, ] 199 // ... 200 TEST(DXCFile, ParseDXILPart) { 201 uint8_t Buffer[] = { 202 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 204 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 205 0x44, 0x58, 0x49, 0x4c, 0x1c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x05, 0x00, 206 0x08, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x05, 0x01, 0x00, 0x00, 207 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde}; 208 DXContainer C = 209 llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer))); 210 EXPECT_EQ(C.getHeader().PartCount, 1u); 211 const std::optional<object::DXContainer::DXILData> &DXIL = C.getDXIL(); 212 EXPECT_TRUE(DXIL.has_value()); 213 dxbc::ProgramHeader Header = DXIL->first; 214 EXPECT_EQ(Header.getMajorVersion(), 6u); 215 EXPECT_EQ(Header.getMinorVersion(), 5u); 216 EXPECT_EQ(Header.ShaderKind, 5u); 217 EXPECT_EQ(Header.Size, 8u); 218 EXPECT_EQ(Header.Bitcode.MajorVersion, 1u); 219 EXPECT_EQ(Header.Bitcode.MinorVersion, 5u); 220 } 221 222 static Expected<DXContainer> 223 generateDXContainer(StringRef Yaml, SmallVectorImpl<char> &BinaryData) { 224 DXContainerYAML::Object Obj; 225 SMDiagnostic GenerateDiag; 226 yaml::Input YIn( 227 Yaml, /*Ctxt=*/nullptr, 228 [](const SMDiagnostic &Diag, void *DiagContext) { 229 *static_cast<SMDiagnostic *>(DiagContext) = Diag; 230 }, 231 &GenerateDiag); 232 233 YIn >> Obj; 234 if (YIn.error()) 235 return createStringError(YIn.error(), GenerateDiag.getMessage()); 236 237 raw_svector_ostream OS(BinaryData); 238 std::string ErrorMsg; 239 if (!yaml::yaml2dxcontainer( 240 Obj, OS, [&ErrorMsg](const Twine &Msg) { ErrorMsg = Msg.str(); })) 241 return createStringError(YIn.error(), ErrorMsg); 242 243 MemoryBufferRef BinaryDataRef = MemoryBufferRef(OS.str(), ""); 244 245 return DXContainer::create(BinaryDataRef); 246 } 247 248 TEST(DXCFile, PSVResourceIterators) { 249 const char *Yaml = R"( 250 --- !dxcontainer 251 Header: 252 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 253 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 254 Version: 255 Major: 1 256 Minor: 0 257 PartCount: 2 258 Parts: 259 - Name: PSV0 260 Size: 144 261 PSVInfo: 262 Version: 0 263 ShaderStage: 14 264 PayloadSizeInBytes: 4092 265 MinimumWaveLaneCount: 0 266 MaximumWaveLaneCount: 4294967295 267 ResourceStride: 16 268 Resources: 269 - Type: Sampler 270 Space: 1 271 LowerBound: 1 272 UpperBound: 1 273 - Type: CBV 274 Space: 2 275 LowerBound: 2 276 UpperBound: 2 277 - Type: SRVTyped 278 Space: 3 279 LowerBound: 3 280 UpperBound: 3 281 - Name: DXIL 282 Size: 24 283 Program: 284 MajorVersion: 6 285 MinorVersion: 0 286 ShaderKind: 14 287 Size: 6 288 DXILMajorVersion: 1 289 DXILMinorVersion: 0 290 DXILSize: 0 291 ... 292 )"; 293 294 SmallVector<char, 256> BinaryData; 295 auto C = generateDXContainer(Yaml, BinaryData); 296 297 ASSERT_THAT_EXPECTED(C, Succeeded()); 298 299 const auto &PSVInfo = C->getPSVInfo(); 300 ASSERT_TRUE(PSVInfo.has_value()); 301 302 EXPECT_EQ(PSVInfo->getResourceCount(), 3u); 303 304 auto It = PSVInfo->getResources().begin(); 305 306 EXPECT_TRUE(It == PSVInfo->getResources().begin()); 307 308 dxbc::PSV::v2::ResourceBindInfo Binding; 309 310 Binding = *It; 311 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 312 EXPECT_EQ(Binding.Flags, 0u); 313 314 ++It; 315 Binding = *It; 316 317 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::CBV); 318 EXPECT_EQ(Binding.Flags, 0u); 319 320 --It; 321 Binding = *It; 322 323 EXPECT_TRUE(It == PSVInfo->getResources().begin()); 324 325 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 326 EXPECT_EQ(Binding.Flags, 0u); 327 328 --It; 329 Binding = *It; 330 331 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 332 EXPECT_EQ(Binding.Flags, 0u); 333 334 ++It; 335 Binding = *It; 336 337 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::CBV); 338 EXPECT_EQ(Binding.Flags, 0u); 339 340 ++It; 341 Binding = *It; 342 343 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVTyped); 344 EXPECT_EQ(Binding.Flags, 0u); 345 346 EXPECT_FALSE(It == PSVInfo->getResources().end()); 347 348 ++It; 349 Binding = *It; 350 351 EXPECT_TRUE(It == PSVInfo->getResources().end()); 352 EXPECT_FALSE(It != PSVInfo->getResources().end()); 353 354 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid); 355 EXPECT_EQ(Binding.Flags, 0u); 356 357 { 358 auto Old = It++; 359 Binding = *Old; 360 361 EXPECT_TRUE(Old == PSVInfo->getResources().end()); 362 EXPECT_FALSE(Old != PSVInfo->getResources().end()); 363 364 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid); 365 EXPECT_EQ(Binding.Flags, 0u); 366 } 367 368 Binding = *It; 369 370 EXPECT_TRUE(It == PSVInfo->getResources().end()); 371 372 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid); 373 EXPECT_EQ(Binding.Flags, 0u); 374 375 { 376 auto Old = It--; 377 Binding = *Old; 378 EXPECT_TRUE(Old == PSVInfo->getResources().end()); 379 380 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid); 381 EXPECT_EQ(Binding.Flags, 0u); 382 } 383 384 Binding = *It; 385 386 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVTyped); 387 EXPECT_EQ(Binding.Flags, 0u); 388 } 389 390 // The malicious file bits in these tests are mutations of the binary produced 391 // by the following YAML: 392 // 393 // --- !dxcontainer 394 // Header: 395 // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 396 // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 397 // Version: 398 // Major: 1 399 // Minor: 0 400 // PartCount: 3 401 // Parts: 402 // - Name: DXIL 403 // Size: 24 404 // Program: 405 // MajorVersion: 6 406 // MinorVersion: 0 407 // ShaderKind: 14 408 // Size: 6 409 // DXILMajorVersion: 1 410 // DXILMinorVersion: 0 411 // DXILSize: 0 412 // - Name: PSV0 413 // Size: 36 414 // PSVInfo: 415 // Version: 0 416 // ShaderStage: 5 417 // MinimumWaveLaneCount: 0 418 // MaximumWaveLaneCount: 0 419 // ResourceStride: 16 420 // Resources: [] 421 // - Name: BLEH 422 // Size: 16 423 // ... 424 425 TEST(DXCFile, MaliciousFiles) { 426 427 // In this file blob, the file size is specified as 96 bytes (0x60), and the 428 // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of 429 // the file. 430 { 431 uint8_t Buffer[] = { 432 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 434 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 435 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, 436 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 437 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 438 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 440 }; 441 EXPECT_THAT_EXPECTED( 442 DXContainer::create(getMemoryBuffer<96>(Buffer)), 443 FailedWithMessage( 444 "Pipeline state data extends beyond the bounds of the part")); 445 } 446 447 // PSV extends beyond part, but in file range. In this blob the file size is 448 // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is 449 // 40 bytes (0x40). 450 { 451 uint8_t Buffer[] = { 452 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 454 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 455 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 456 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 457 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 459 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 462 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 464 }; 465 EXPECT_THAT_EXPECTED( 466 DXContainer::create(getMemoryBuffer<144>(Buffer)), 467 FailedWithMessage( 468 "Pipeline state data extends beyond the bounds of the part")); 469 } 470 471 // In this file blob, the file is 116 bytes (0x74). The file structure is 472 // valid except that it specifies 1 16 byte resource binding which would 473 // extend beyond the range of the part and file. 474 { 475 uint8_t Buffer[] = { 476 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 478 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 479 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, 480 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 481 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 482 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 485 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 486 }; 487 EXPECT_THAT_EXPECTED( 488 DXContainer::create(getMemoryBuffer<116>(Buffer)), 489 FailedWithMessage( 490 "Resource binding data extends beyond the bounds of the part")); 491 } 492 493 // In this file blob, the file is 116 bytes (0x74). The file structure is 494 // valid except that it specifies 1 16 byte resource binding which would 495 // extend beyond the range of the part and into the `BLEH` part. 496 { 497 uint8_t Buffer[] = { 498 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 500 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 501 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 502 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 503 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 504 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 505 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 507 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 508 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 510 }; 511 EXPECT_THAT_EXPECTED( 512 DXContainer::create(getMemoryBuffer<144>(Buffer)), 513 FailedWithMessage( 514 "Resource binding data extends beyond the bounds of the part")); 515 } 516 } 517 518 // This test verifies that the resource iterator follows the stride even if the 519 // stride doesn't match an expected or known value. In this test, the resource 520 // data is structured validly, with 32 bytes per resource. This test is based on 521 // editing the binary output constructed from this yaml. 522 // 523 // --- !dxcontainer 524 // Header: 525 // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 526 // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 527 // Version: 528 // Major: 1 529 // Minor: 0 530 // PartCount: 2 531 // Parts: 532 // - Name: DXIL 533 // Size: 24 534 // Program: 535 // MajorVersion: 6 536 // MinorVersion: 0 537 // ShaderKind: 14 538 // Size: 6 539 // DXILMajorVersion: 1 540 // DXILMinorVersion: 0 541 // DXILSize: 0 542 // - Name: PSV0 543 // Size: 100 544 // PSVInfo: 545 // Version: 0 546 // ShaderStage: 5 547 // MinimumWaveLaneCount: 0 548 // MaximumWaveLaneCount: 0 549 // ResourceStride: 16 550 // Resources: 551 // - Type: 1 552 // Space: 2 553 // LowerBound: 3 554 // UpperBound: 4 555 // - Type: 5 556 // Space: 6 557 // LowerBound: 7 558 // UpperBound: 8 559 // ... 560 TEST(DXCFile, PSVResourceIteratorsStride) { 561 uint8_t Buffer[] = { 562 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 563 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 564 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, 565 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 566 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00, 567 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 569 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 570 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 571 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 572 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 573 0x00, 0x00, 0x00, 0x00, 574 }; 575 DXContainer C = 576 llvm::cantFail(DXContainer::create(getMemoryBuffer<180>(Buffer))); 577 578 const auto &PSVInfo = C.getPSVInfo(); 579 ASSERT_TRUE(PSVInfo.has_value()); 580 581 ASSERT_EQ(PSVInfo->getResourceCount(), 2u); 582 583 auto It = PSVInfo->getResources().begin(); 584 585 EXPECT_TRUE(It == PSVInfo->getResources().begin()); 586 587 dxbc::PSV::v2::ResourceBindInfo Binding; 588 589 Binding = *It; 590 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 591 EXPECT_EQ(Binding.Space, 2u); 592 EXPECT_EQ(Binding.LowerBound, 3u); 593 EXPECT_EQ(Binding.UpperBound, 4u); 594 595 ++It; 596 Binding = *It; 597 598 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVStructured); 599 EXPECT_EQ(Binding.Space, 6u); 600 EXPECT_EQ(Binding.LowerBound, 7u); 601 EXPECT_EQ(Binding.UpperBound, 8u); 602 603 --It; 604 Binding = *It; 605 606 EXPECT_TRUE(It == PSVInfo->getResources().begin()); 607 608 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 609 EXPECT_EQ(Binding.Space, 2u); 610 EXPECT_EQ(Binding.LowerBound, 3u); 611 EXPECT_EQ(Binding.UpperBound, 4u); 612 613 --It; 614 Binding = *It; 615 616 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler); 617 EXPECT_EQ(Binding.Space, 2u); 618 EXPECT_EQ(Binding.LowerBound, 3u); 619 EXPECT_EQ(Binding.UpperBound, 4u); 620 621 ++It; 622 Binding = *It; 623 624 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVStructured); 625 EXPECT_EQ(Binding.Space, 6u); 626 EXPECT_EQ(Binding.LowerBound, 7u); 627 EXPECT_EQ(Binding.UpperBound, 8u);; 628 629 630 EXPECT_FALSE(It == PSVInfo->getResources().end()); 631 632 ++It; 633 Binding = *It; 634 635 EXPECT_TRUE(It == PSVInfo->getResources().end()); 636 EXPECT_FALSE(It != PSVInfo->getResources().end()); 637 638 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid); 639 EXPECT_EQ(Binding.Flags, 0u); 640 } 641 642 // This test binary is created using mutations of the yaml in the SigElements 643 // test found under test/ObjectYAML/DXContainer/SigElements.yaml. 644 645 TEST(DXCFile, MisalignedStringTable) { 646 uint8_t Buffer[] = { 647 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 649 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 650 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00, 651 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 652 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 653 0x50, 0x53, 0x56, 0x30, 0x68, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 656 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40, 657 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 658 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 661 EXPECT_THAT_EXPECTED(DXContainer::create(getMemoryBuffer<168>(Buffer)), 662 FailedWithMessage("String table misaligned")); 663 } 664 665 // This test binary is created using mutations of the yaml in the SigElements 666 // test found under test/ObjectYAML/DXContainer/SigElements.yaml. 667 TEST(DXCFile, SigElementsExtendBeyondPart) { 668 uint8_t Buffer[] = { 669 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 671 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 672 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00, 673 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 674 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 675 0x50, 0x53, 0x56, 0x30, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 678 0x05, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40, 679 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x00, 680 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 681 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 682 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x03, 0x00}; 683 EXPECT_THAT_EXPECTED( 684 DXContainer::create(getMemoryBuffer<164>(Buffer)), 685 FailedWithMessage( 686 "Signature elements extend beyond the size of the part")); 687 } 688 689 TEST(DXCFile, MalformedSignature) { 690 /* 691 The tests here exercise the DXContainer Signature section parser. These tests 692 are based on modifying the binary described by the following yaml: 693 694 --- !dxcontainer 695 Header: 696 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 697 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 698 Version: 699 Major: 1 700 Minor: 0 701 FileSize: 128 702 PartCount: 1 703 PartOffsets: [ 64 ] 704 Parts: 705 - Name: ISG1 706 Size: 52 707 Signature: 708 Parameters: 709 - Stream: 0 710 Name: AAA 711 Index: 0 712 SystemValue: Undefined 713 CompType: Float32 714 Register: 0 715 Mask: 7 716 ExclusiveMask: 2 717 MinPrecision: Default 718 ... 719 720 The unmodified hex sequence is: 721 722 uint8_t Buffer[] = { 723 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 725 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 728 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 731 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 733 }; 734 735 */ 736 737 { 738 739 // This binary says the signature has 10 parameters, but the part data is 740 // only big enough for 1. 741 uint8_t Buffer[] = { 742 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 744 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 747 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 748 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 749 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 750 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 751 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 752 0x00, 0x00, 0x00, 0x00}; 753 EXPECT_THAT_EXPECTED( 754 DXContainer::create(getMemoryBuffer<164>(Buffer)), 755 FailedWithMessage( 756 "Signature parameters extend beyond the part boundary")); 757 } 758 759 { 760 761 // This binary only has one parameter, but the start offset is beyond the 762 // size of the part. 763 uint8_t Buffer[] = { 764 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 766 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 769 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 770 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 771 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 772 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 773 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 774 0x00, 0x00, 0x00, 0x00}; 775 EXPECT_THAT_EXPECTED( 776 DXContainer::create(getMemoryBuffer<164>(Buffer)), 777 FailedWithMessage( 778 "Signature parameters extend beyond the part boundary")); 779 } 780 781 { 782 783 // This parameter has a name offset of 3, which is before the start of the 784 // string table. 785 uint8_t Buffer[] = { 786 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 788 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 791 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 792 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 793 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 794 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 795 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 796 0x00, 0x00, 0x00, 0x00}; 797 EXPECT_THAT_EXPECTED( 798 DXContainer::create(getMemoryBuffer<164>(Buffer)), 799 FailedWithMessage("Invalid parameter name offset: name starts before " 800 "the first name offset")); 801 } 802 803 { 804 // This parameter has a name offset of 255, which is after the end of the 805 // part. 806 uint8_t Buffer[] = { 807 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 809 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 812 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 813 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 814 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 815 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 816 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 817 0x00, 0x00, 0x00, 0x00}; 818 EXPECT_THAT_EXPECTED( 819 DXContainer::create(getMemoryBuffer<164>(Buffer)), 820 FailedWithMessage("Invalid parameter name offset: name starts after " 821 "the end of the part data")); 822 } 823 } 824