xref: /llvm-project/llvm/unittests/Object/DXContainerTest.cpp (revision fd0dbc7f4d8a5900535aa87569fbc385b7c50ba6)
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