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(ValOrErr: DXContainer::create(Object: getMemoryBuffer<32>(Data: 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(ValOrErr: DXContainer::create(Object: getMemoryBuffer<116>(Data: 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 | static Expected<DXContainer> |
178 | generateDXContainer(StringRef Yaml, SmallVectorImpl<char> &BinaryData) { |
179 | DXContainerYAML::Object Obj; |
180 | SMDiagnostic GenerateDiag; |
181 | yaml::Input YIn( |
182 | Yaml, /*Ctxt=*/nullptr, |
183 | [](const SMDiagnostic &Diag, void *DiagContext) { |
184 | *static_cast<SMDiagnostic *>(DiagContext) = Diag; |
185 | }, |
186 | &GenerateDiag); |
187 | |
188 | YIn >> Obj; |
189 | if (YIn.error()) |
190 | return createStringError(EC: YIn.error(), S: GenerateDiag.getMessage()); |
191 | |
192 | raw_svector_ostream OS(BinaryData); |
193 | std::string ErrorMsg; |
194 | if (!yaml::yaml2dxcontainer( |
195 | Doc&: Obj, Out&: OS, EH: [&ErrorMsg](const Twine &Msg) { ErrorMsg = Msg.str(); })) |
196 | return createStringError(EC: YIn.error(), S: ErrorMsg); |
197 | |
198 | MemoryBufferRef BinaryDataRef = MemoryBufferRef(OS.str(), "" ); |
199 | |
200 | return DXContainer::create(Object: BinaryDataRef); |
201 | } |
202 | |
203 | TEST(DXCFile, PSVResourceIterators) { |
204 | const char *Yaml = R"( |
205 | --- !dxcontainer |
206 | Header: |
207 | Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
208 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] |
209 | Version: |
210 | Major: 1 |
211 | Minor: 0 |
212 | PartCount: 2 |
213 | Parts: |
214 | - Name: PSV0 |
215 | Size: 144 |
216 | PSVInfo: |
217 | Version: 0 |
218 | ShaderStage: 14 |
219 | PayloadSizeInBytes: 4092 |
220 | MinimumWaveLaneCount: 0 |
221 | MaximumWaveLaneCount: 4294967295 |
222 | ResourceStride: 16 |
223 | Resources: |
224 | - Type: 1 |
225 | Space: 1 |
226 | LowerBound: 1 |
227 | UpperBound: 1 |
228 | - Type: 2 |
229 | Space: 2 |
230 | LowerBound: 2 |
231 | UpperBound: 2 |
232 | - Type: 3 |
233 | Space: 3 |
234 | LowerBound: 3 |
235 | UpperBound: 3 |
236 | - Name: DXIL |
237 | Size: 24 |
238 | Program: |
239 | MajorVersion: 6 |
240 | MinorVersion: 0 |
241 | ShaderKind: 14 |
242 | Size: 6 |
243 | DXILMajorVersion: 0 |
244 | DXILMinorVersion: 1 |
245 | DXILSize: 0 |
246 | ... |
247 | )" ; |
248 | |
249 | SmallVector<char, 256> BinaryData; |
250 | auto C = generateDXContainer(Yaml, BinaryData); |
251 | |
252 | ASSERT_THAT_EXPECTED(C, Succeeded()); |
253 | |
254 | const auto &PSVInfo = C->getPSVInfo(); |
255 | ASSERT_TRUE(PSVInfo.has_value()); |
256 | |
257 | EXPECT_EQ(PSVInfo->getResourceCount(), 3u); |
258 | |
259 | auto It = PSVInfo->getResources().begin(); |
260 | |
261 | EXPECT_TRUE(It == PSVInfo->getResources().begin()); |
262 | |
263 | dxbc::PSV::v2::ResourceBindInfo Binding; |
264 | |
265 | Binding = *It; |
266 | EXPECT_EQ(Binding.Type, 1u); |
267 | EXPECT_EQ(Binding.Flags, 0u); |
268 | |
269 | ++It; |
270 | Binding = *It; |
271 | |
272 | EXPECT_EQ(Binding.Type, 2u); |
273 | EXPECT_EQ(Binding.Flags, 0u); |
274 | |
275 | --It; |
276 | Binding = *It; |
277 | |
278 | EXPECT_TRUE(It == PSVInfo->getResources().begin()); |
279 | |
280 | EXPECT_EQ(Binding.Type, 1u); |
281 | EXPECT_EQ(Binding.Flags, 0u); |
282 | |
283 | --It; |
284 | Binding = *It; |
285 | |
286 | EXPECT_EQ(Binding.Type, 1u); |
287 | EXPECT_EQ(Binding.Flags, 0u); |
288 | |
289 | ++It; |
290 | Binding = *It; |
291 | |
292 | EXPECT_EQ(Binding.Type, 2u); |
293 | EXPECT_EQ(Binding.Flags, 0u); |
294 | |
295 | ++It; |
296 | Binding = *It; |
297 | |
298 | EXPECT_EQ(Binding.Type, 3u); |
299 | EXPECT_EQ(Binding.Flags, 0u); |
300 | |
301 | EXPECT_FALSE(It == PSVInfo->getResources().end()); |
302 | |
303 | ++It; |
304 | Binding = *It; |
305 | |
306 | EXPECT_TRUE(It == PSVInfo->getResources().end()); |
307 | EXPECT_FALSE(It != PSVInfo->getResources().end()); |
308 | |
309 | EXPECT_EQ(Binding.Type, 0u); |
310 | EXPECT_EQ(Binding.Flags, 0u); |
311 | |
312 | { |
313 | auto Old = It++; |
314 | Binding = *Old; |
315 | |
316 | EXPECT_TRUE(Old == PSVInfo->getResources().end()); |
317 | EXPECT_FALSE(Old != PSVInfo->getResources().end()); |
318 | |
319 | EXPECT_EQ(Binding.Type, 0u); |
320 | EXPECT_EQ(Binding.Flags, 0u); |
321 | } |
322 | |
323 | Binding = *It; |
324 | |
325 | EXPECT_TRUE(It == PSVInfo->getResources().end()); |
326 | |
327 | EXPECT_EQ(Binding.Type, 0u); |
328 | EXPECT_EQ(Binding.Flags, 0u); |
329 | |
330 | { |
331 | auto Old = It--; |
332 | Binding = *Old; |
333 | EXPECT_TRUE(Old == PSVInfo->getResources().end()); |
334 | |
335 | EXPECT_EQ(Binding.Type, 0u); |
336 | EXPECT_EQ(Binding.Flags, 0u); |
337 | } |
338 | |
339 | Binding = *It; |
340 | |
341 | EXPECT_EQ(Binding.Type, 3u); |
342 | EXPECT_EQ(Binding.Flags, 0u); |
343 | } |
344 | |
345 | // The malicious file bits in these tests are mutations of the binary produced |
346 | // by the following YAML: |
347 | // |
348 | // --- !dxcontainer |
349 | // Header: |
350 | // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
351 | // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] |
352 | // Version: |
353 | // Major: 1 |
354 | // Minor: 0 |
355 | // PartCount: 3 |
356 | // Parts: |
357 | // - Name: DXIL |
358 | // Size: 24 |
359 | // Program: |
360 | // MajorVersion: 6 |
361 | // MinorVersion: 0 |
362 | // ShaderKind: 14 |
363 | // Size: 6 |
364 | // DXILMajorVersion: 0 |
365 | // DXILMinorVersion: 1 |
366 | // DXILSize: 0 |
367 | // - Name: PSV0 |
368 | // Size: 36 |
369 | // PSVInfo: |
370 | // Version: 0 |
371 | // ShaderStage: 5 |
372 | // MinimumWaveLaneCount: 0 |
373 | // MaximumWaveLaneCount: 0 |
374 | // ResourceStride: 16 |
375 | // Resources: [] |
376 | // - Name: BLEH |
377 | // Size: 16 |
378 | // ... |
379 | |
380 | TEST(DXCFile, MaliciousFiles) { |
381 | |
382 | // In this file blob, the file size is specified as 96 bytes (0x60), and the |
383 | // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of |
384 | // the file. |
385 | { |
386 | uint8_t Buffer[] = { |
387 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
388 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
389 | 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, |
390 | 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, |
391 | 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, |
392 | 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
393 | 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, |
394 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
395 | }; |
396 | EXPECT_THAT_EXPECTED( |
397 | DXContainer::create(getMemoryBuffer<96>(Buffer)), |
398 | FailedWithMessage( |
399 | "Pipeline state data extends beyond the bounds of the part" )); |
400 | } |
401 | |
402 | // PSV extends beyond part, but in file range. In this blob the file size is |
403 | // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is |
404 | // 40 bytes (0x40). |
405 | { |
406 | uint8_t Buffer[] = { |
407 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
408 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
409 | 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, |
410 | 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, |
411 | 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, |
412 | 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
413 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, |
414 | 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
415 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
416 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
417 | 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
418 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
419 | }; |
420 | EXPECT_THAT_EXPECTED( |
421 | DXContainer::create(getMemoryBuffer<144>(Buffer)), |
422 | FailedWithMessage( |
423 | "Pipeline state data extends beyond the bounds of the part" )); |
424 | } |
425 | |
426 | // In this file blob, the file is 116 bytes (0x74). The file structure is |
427 | // valid except that it specifies 1 16 byte resource binding which would |
428 | // extend beyond the range of the part and file. |
429 | { |
430 | uint8_t Buffer[] = { |
431 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
432 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
433 | 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, |
434 | 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, |
435 | 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, |
436 | 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
437 | 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, |
438 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
439 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
440 | 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
441 | }; |
442 | EXPECT_THAT_EXPECTED( |
443 | DXContainer::create(getMemoryBuffer<116>(Buffer)), |
444 | FailedWithMessage( |
445 | "Resource binding data extends beyond the bounds of the part" )); |
446 | } |
447 | |
448 | // In this file blob, the file is 116 bytes (0x74). The file structure is |
449 | // valid except that it specifies 1 16 byte resource binding which would |
450 | // extend beyond the range of the part and into the `BLEH` part. |
451 | { |
452 | uint8_t Buffer[] = { |
453 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
454 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
455 | 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, |
456 | 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, |
457 | 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, |
458 | 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
459 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, |
460 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
461 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
462 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
463 | 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
464 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
465 | }; |
466 | EXPECT_THAT_EXPECTED( |
467 | DXContainer::create(getMemoryBuffer<144>(Buffer)), |
468 | FailedWithMessage( |
469 | "Resource binding data extends beyond the bounds of the part" )); |
470 | } |
471 | } |
472 | |
473 | // This test verifies that the resource iterator follows the stride even if the |
474 | // stride doesn't match an expected or known value. In this test, the resource |
475 | // data is structured validly, with 32 bytes per resource. This test is based on |
476 | // editing the binary output constructed from this yaml. |
477 | // |
478 | // --- !dxcontainer |
479 | // Header: |
480 | // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
481 | // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] |
482 | // Version: |
483 | // Major: 1 |
484 | // Minor: 0 |
485 | // PartCount: 2 |
486 | // Parts: |
487 | // - Name: DXIL |
488 | // Size: 24 |
489 | // Program: |
490 | // MajorVersion: 6 |
491 | // MinorVersion: 0 |
492 | // ShaderKind: 14 |
493 | // Size: 6 |
494 | // DXILMajorVersion: 0 |
495 | // DXILMinorVersion: 1 |
496 | // DXILSize: 0 |
497 | // - Name: PSV0 |
498 | // Size: 100 |
499 | // PSVInfo: |
500 | // Version: 0 |
501 | // ShaderStage: 5 |
502 | // MinimumWaveLaneCount: 0 |
503 | // MaximumWaveLaneCount: 0 |
504 | // ResourceStride: 16 |
505 | // Resources: |
506 | // - Type: 1 |
507 | // Space: 2 |
508 | // LowerBound: 3 |
509 | // UpperBound: 4 |
510 | // - Type: 5 |
511 | // Space: 6 |
512 | // LowerBound: 7 |
513 | // UpperBound: 8 |
514 | // ... |
515 | TEST(DXCFile, PSVResourceIteratorsStride) { |
516 | uint8_t Buffer[] = { |
517 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
518 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
519 | 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00, |
520 | 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, |
521 | 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00, |
522 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
523 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
524 | 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
525 | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
526 | 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, |
527 | 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
528 | 0x00, 0x00, 0x00, 0x00, |
529 | }; |
530 | DXContainer C = |
531 | llvm::cantFail(ValOrErr: DXContainer::create(Object: getMemoryBuffer<180>(Data: Buffer))); |
532 | |
533 | const auto &PSVInfo = C.getPSVInfo(); |
534 | ASSERT_TRUE(PSVInfo.has_value()); |
535 | |
536 | ASSERT_EQ(PSVInfo->getResourceCount(), 2u); |
537 | |
538 | auto It = PSVInfo->getResources().begin(); |
539 | |
540 | EXPECT_TRUE(It == PSVInfo->getResources().begin()); |
541 | |
542 | dxbc::PSV::v2::ResourceBindInfo Binding; |
543 | |
544 | Binding = *It; |
545 | EXPECT_EQ(Binding.Type, 1u); |
546 | EXPECT_EQ(Binding.Space, 2u); |
547 | EXPECT_EQ(Binding.LowerBound, 3u); |
548 | EXPECT_EQ(Binding.UpperBound, 4u); |
549 | |
550 | ++It; |
551 | Binding = *It; |
552 | |
553 | EXPECT_EQ(Binding.Type, 5u); |
554 | EXPECT_EQ(Binding.Space, 6u); |
555 | EXPECT_EQ(Binding.LowerBound, 7u); |
556 | EXPECT_EQ(Binding.UpperBound, 8u); |
557 | |
558 | --It; |
559 | Binding = *It; |
560 | |
561 | EXPECT_TRUE(It == PSVInfo->getResources().begin()); |
562 | |
563 | EXPECT_EQ(Binding.Type, 1u); |
564 | EXPECT_EQ(Binding.Space, 2u); |
565 | EXPECT_EQ(Binding.LowerBound, 3u); |
566 | EXPECT_EQ(Binding.UpperBound, 4u); |
567 | |
568 | --It; |
569 | Binding = *It; |
570 | |
571 | EXPECT_EQ(Binding.Type, 1u); |
572 | EXPECT_EQ(Binding.Space, 2u); |
573 | EXPECT_EQ(Binding.LowerBound, 3u); |
574 | EXPECT_EQ(Binding.UpperBound, 4u); |
575 | |
576 | ++It; |
577 | Binding = *It; |
578 | |
579 | EXPECT_EQ(Binding.Type, 5u); |
580 | EXPECT_EQ(Binding.Space, 6u); |
581 | EXPECT_EQ(Binding.LowerBound, 7u); |
582 | EXPECT_EQ(Binding.UpperBound, 8u);; |
583 | |
584 | |
585 | EXPECT_FALSE(It == PSVInfo->getResources().end()); |
586 | |
587 | ++It; |
588 | Binding = *It; |
589 | |
590 | EXPECT_TRUE(It == PSVInfo->getResources().end()); |
591 | EXPECT_FALSE(It != PSVInfo->getResources().end()); |
592 | |
593 | EXPECT_EQ(Binding.Type, 0u); |
594 | EXPECT_EQ(Binding.Flags, 0u); |
595 | } |
596 | |
597 | // This test binary is created using mutations of the yaml in the SigElements |
598 | // test found under test/ObjectYAML/DXContainer/SigElements.yaml. |
599 | |
600 | TEST(DXCFile, MisalignedStringTable) { |
601 | uint8_t Buffer[] = { |
602 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
604 | 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, |
605 | 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00, |
606 | 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, |
607 | 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
608 | 0x50, 0x53, 0x56, 0x30, 0x68, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, |
609 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, |
611 | 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40, |
612 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
613 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
614 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
616 | EXPECT_THAT_EXPECTED(DXContainer::create(getMemoryBuffer<168>(Buffer)), |
617 | FailedWithMessage("String table misaligned" )); |
618 | } |
619 | |
620 | // This test binary is created using mutations of the yaml in the SigElements |
621 | // test found under test/ObjectYAML/DXContainer/SigElements.yaml. |
622 | TEST(DXCFile, SigElementsExtendBeyondPart) { |
623 | uint8_t Buffer[] = { |
624 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
625 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
626 | 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, |
627 | 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00, |
628 | 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, |
629 | 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
630 | 0x50, 0x53, 0x56, 0x30, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, |
631 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
632 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, |
633 | 0x05, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40, |
634 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x00, |
635 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
636 | 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
637 | 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x03, 0x00}; |
638 | EXPECT_THAT_EXPECTED( |
639 | DXContainer::create(getMemoryBuffer<164>(Buffer)), |
640 | FailedWithMessage( |
641 | "Signature elements extend beyond the size of the part" )); |
642 | } |
643 | |
644 | TEST(DXCFile, MalformedSignature) { |
645 | /* |
646 | The tests here exercise the DXContainer Signature section parser. These tests |
647 | are based on modifying the binary described by the following yaml: |
648 | |
649 | --- !dxcontainer |
650 | Header: |
651 | Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
652 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] |
653 | Version: |
654 | Major: 1 |
655 | Minor: 0 |
656 | FileSize: 128 |
657 | PartCount: 1 |
658 | PartOffsets: [ 64 ] |
659 | Parts: |
660 | - Name: ISG1 |
661 | Size: 52 |
662 | Signature: |
663 | Parameters: |
664 | - Stream: 0 |
665 | Name: AAA |
666 | Index: 0 |
667 | SystemValue: Undefined |
668 | CompType: Float32 |
669 | Register: 0 |
670 | Mask: 7 |
671 | ExclusiveMask: 2 |
672 | MinPrecision: Default |
673 | ... |
674 | |
675 | The unmodified hex sequence is: |
676 | |
677 | uint8_t Buffer[] = { |
678 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
679 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, |
680 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
681 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
682 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
683 | 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, |
684 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, |
685 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
686 | 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, |
687 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
688 | }; |
689 | |
690 | */ |
691 | |
692 | { |
693 | |
694 | // This binary says the signature has 10 parameters, but the part data is |
695 | // only big enough for 1. |
696 | uint8_t Buffer[] = { |
697 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
698 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
699 | 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, |
700 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
701 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
702 | 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, |
703 | 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
704 | 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
705 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, |
706 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, |
707 | 0x00, 0x00, 0x00, 0x00}; |
708 | EXPECT_THAT_EXPECTED( |
709 | DXContainer::create(getMemoryBuffer<164>(Buffer)), |
710 | FailedWithMessage( |
711 | "Signature parameters extend beyond the part boundary" )); |
712 | } |
713 | |
714 | { |
715 | |
716 | // This binary only has one parameter, but the start offset is beyond the |
717 | // size of the part. |
718 | uint8_t Buffer[] = { |
719 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
720 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
721 | 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, |
722 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
723 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
724 | 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, |
725 | 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
726 | 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
727 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, |
728 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, |
729 | 0x00, 0x00, 0x00, 0x00}; |
730 | EXPECT_THAT_EXPECTED( |
731 | DXContainer::create(getMemoryBuffer<164>(Buffer)), |
732 | FailedWithMessage( |
733 | "Signature parameters extend beyond the part boundary" )); |
734 | } |
735 | |
736 | { |
737 | |
738 | // This parameter has a name offset of 3, which is before the start of the |
739 | // string table. |
740 | uint8_t Buffer[] = { |
741 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
742 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
743 | 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, |
744 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
745 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
746 | 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, |
747 | 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
748 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
749 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, |
750 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, |
751 | 0x00, 0x00, 0x00, 0x00}; |
752 | EXPECT_THAT_EXPECTED( |
753 | DXContainer::create(getMemoryBuffer<164>(Buffer)), |
754 | FailedWithMessage("Invalid parameter name offset: name starts before " |
755 | "the first name offset" )); |
756 | } |
757 | |
758 | { |
759 | // This parameter has a name offset of 255, which is after the end of the |
760 | // part. |
761 | uint8_t Buffer[] = { |
762 | 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
763 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
764 | 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, |
765 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
766 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
767 | 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, |
768 | 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
769 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
770 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, |
771 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, |
772 | 0x00, 0x00, 0x00, 0x00}; |
773 | EXPECT_THAT_EXPECTED( |
774 | DXContainer::create(getMemoryBuffer<164>(Buffer)), |
775 | FailedWithMessage("Invalid parameter name offset: name starts after " |
776 | "the end of the part data" )); |
777 | } |
778 | } |
779 | |