PayloadSizeInBytes: 4092
MinimumWaveLaneCount: 0
MaximumWaveLaneCount: 4294967295
+ ResourceStride: 16
Resources:
- Type: 1
Space: 1
EXPECT_EQ(Binding.Type, 0u);
EXPECT_EQ(Binding.Flags, 0u);
}
-
+
Binding = *It;
EXPECT_EQ(Binding.Type, 3u);
EXPECT_EQ(Binding.Flags, 0u);
}
+
+// The malicious file bits in these tests are mutations of the binary produced
+// by the following YAML:
+//
+// --- !dxcontainer
+// Header:
+// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+// Version:
+// Major: 1
+// Minor: 0
+// PartCount: 3
+// Parts:
+// - Name: DXIL
+// Size: 24
+// Program:
+// MajorVersion: 6
+// MinorVersion: 0
+// ShaderKind: 14
+// Size: 6
+// DXILMajorVersion: 0
+// DXILMinorVersion: 1
+// DXILSize: 0
+// - Name: PSV0
+// Size: 36
+// PSVInfo:
+// Version: 0
+// ShaderStage: 5
+// MinimumWaveLaneCount: 0
+// MaximumWaveLaneCount: 0
+// ResourceStride: 16
+// Resources: []
+// - Name: BLEH
+// Size: 16
+// ...
+
+TEST(DXCFile, MaliciousFiles) {
+
+ // In this file blob, the file size is specified as 96 bytes (0x60), and the
+ // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of
+ // the file.
+ {
+ uint8_t Buffer[] = {
+ 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+ 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ EXPECT_THAT_EXPECTED(
+ DXContainer::create(getMemoryBuffer<96>(Buffer)),
+ FailedWithMessage(
+ "Pipeline state data extends beyond the bounds of the part"));
+ }
+
+ // PSV extends beyond part, but in file range. In this blob the file size is
+ // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is
+ // 40 bytes (0x40).
+ {
+ uint8_t Buffer[] = {
+ 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
+ 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+ 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ EXPECT_THAT_EXPECTED(
+ DXContainer::create(getMemoryBuffer<144>(Buffer)),
+ FailedWithMessage(
+ "Pipeline state data extends beyond the bounds of the part"));
+ }
+
+ // In this file blob, the file is 116 bytes (0x74). The file structure is
+ // valid except that it specifies 1 16 byte resource binding which would
+ // extend beyond the range of the part and file.
+ {
+ uint8_t Buffer[] = {
+ 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+ 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ };
+ EXPECT_THAT_EXPECTED(
+ DXContainer::create(getMemoryBuffer<116>(Buffer)),
+ FailedWithMessage(
+ "Resource binding data extends beyond the bounds of the part"));
+ }
+
+ // In this file blob, the file is 116 bytes (0x74). The file structure is
+ // valid except that it specifies 1 16 byte resource binding which would
+ // extend beyond the range of the part and into the `BLEH` part.
+ {
+ uint8_t Buffer[] = {
+ 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
+ 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+ 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ EXPECT_THAT_EXPECTED(
+ DXContainer::create(getMemoryBuffer<144>(Buffer)),
+ FailedWithMessage(
+ "Resource binding data extends beyond the bounds of the part"));
+ }
+}
+
+// This test verifies that the resource iterator follows the stride even if the
+// stride doesn't match an expected or known value. In this test, the resource
+// data is structured validly, with 32 bytes per resource. This test is based on
+// editing the binary output constructed from this yaml.
+//
+// --- !dxcontainer
+// Header:
+// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+// Version:
+// Major: 1
+// Minor: 0
+// PartCount: 2
+// Parts:
+// - Name: DXIL
+// Size: 24
+// Program:
+// MajorVersion: 6
+// MinorVersion: 0
+// ShaderKind: 14
+// Size: 6
+// DXILMajorVersion: 0
+// DXILMinorVersion: 1
+// DXILSize: 0
+// - Name: PSV0
+// Size: 100
+// PSVInfo:
+// Version: 0
+// ShaderStage: 5
+// MinimumWaveLaneCount: 0
+// MaximumWaveLaneCount: 0
+// ResourceStride: 16
+// Resources:
+// - Type: 1
+// Space: 2
+// LowerBound: 3
+// UpperBound: 4
+// - Type: 5
+// Space: 6
+// LowerBound: 7
+// UpperBound: 8
+// ...
+TEST(DXCFile, PSVResourceIteratorsStride) {
+ uint8_t Buffer[] = {
+ 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+ DXContainer C =
+ llvm::cantFail(DXContainer::create(getMemoryBuffer<180>(Buffer)));
+
+ const auto &PSVInfo = C.getPSVInfo();
+ ASSERT_TRUE(PSVInfo.has_value());
+
+ ASSERT_EQ(PSVInfo->getResourceCount(), 2u);
+
+ auto It = PSVInfo->getResources().begin();
+
+ EXPECT_TRUE(It == PSVInfo->getResources().begin());
+
+ dxbc::PSV::v2::ResourceBindInfo Binding;
+
+ Binding = *It;
+ EXPECT_EQ(Binding.Type, 1u);
+ EXPECT_EQ(Binding.Space, 2u);
+ EXPECT_EQ(Binding.LowerBound, 3u);
+ EXPECT_EQ(Binding.UpperBound, 4u);
+
+ ++It;
+ Binding = *It;
+
+ EXPECT_EQ(Binding.Type, 5u);
+ EXPECT_EQ(Binding.Space, 6u);
+ EXPECT_EQ(Binding.LowerBound, 7u);
+ EXPECT_EQ(Binding.UpperBound, 8u);
+
+ --It;
+ Binding = *It;
+
+ EXPECT_TRUE(It == PSVInfo->getResources().begin());
+
+ EXPECT_EQ(Binding.Type, 1u);
+ EXPECT_EQ(Binding.Space, 2u);
+ EXPECT_EQ(Binding.LowerBound, 3u);
+ EXPECT_EQ(Binding.UpperBound, 4u);
+
+ --It;
+ Binding = *It;
+
+ EXPECT_EQ(Binding.Type, 1u);
+ EXPECT_EQ(Binding.Space, 2u);
+ EXPECT_EQ(Binding.LowerBound, 3u);
+ EXPECT_EQ(Binding.UpperBound, 4u);
+
+ ++It;
+ Binding = *It;
+
+ EXPECT_EQ(Binding.Type, 5u);
+ EXPECT_EQ(Binding.Space, 6u);
+ EXPECT_EQ(Binding.LowerBound, 7u);
+ EXPECT_EQ(Binding.UpperBound, 8u);;
+
+
+ EXPECT_FALSE(It == PSVInfo->getResources().end());
+
+ ++It;
+ Binding = *It;
+
+ EXPECT_TRUE(It == PSVInfo->getResources().end());
+ EXPECT_FALSE(It != PSVInfo->getResources().end());
+
+ EXPECT_EQ(Binding.Type, 0u);
+ EXPECT_EQ(Binding.Flags, 0u);
+}