diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -35,16 +35,19 @@ // swaps it as appropriate. struct ResourceArray { StringRef Data; - size_t Stride; // size of each element in the list. + uint32_t Stride; // size of each element in the list. ResourceArray() = default; ResourceArray(StringRef D, size_t S) : Data(D), Stride(S) {} using value_type = dxbc::PSV::v2::ResourceBindInfo; + static constexpr uint32_t MaxStride() { + return static_cast(sizeof(value_type)); + } struct iterator { StringRef Data; - size_t Stride; // size of each element in the list. + uint32_t Stride; // size of each element in the list. const char *Current; iterator(const ResourceArray &A, const char *C) @@ -58,7 +61,8 @@ value_type Val = {{0, 0, 0, 0}, 0, 0}; if (Current >= Data.end()) return Val; - memcpy(static_cast(&Val), Current, Stride); + memcpy(static_cast(&Val), Current, + std::min(Stride, MaxStride())); if (sys::IsBigEndianHost) Val.swapBytes(); return Val; @@ -123,6 +127,8 @@ : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo) ? 1 : 0); } + uint32_t getResourceStride() const { return Resources.Stride; } + const InfoStruct &getInfo() const { return BasicInfo; } }; diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h --- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h +++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h @@ -80,6 +80,7 @@ uint32_t Version; dxbc::PSV::v2::RuntimeInfo Info; + uint32_t ResourceStride; std::vector Resources; void mapInfoForVersion(yaml::IO &IO); diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp --- a/llvm/lib/MC/DXContainerPSVInfo.cpp +++ b/llvm/lib/MC/DXContainerPSVInfo.cpp @@ -16,16 +16,20 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const { uint32_t InfoSize; + uint32_t BindingSize; switch (Version) { case 0: InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo); + BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo); break; case 1: InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo); + BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo); break; case 2: default: InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo); + BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo); } uint32_t InfoSizeSwapped = InfoSize; if (sys::IsBigEndianHost) @@ -40,8 +44,7 @@ sys::swapByteOrder(ResourceCount); OS.write(reinterpret_cast(&ResourceCount), sizeof(uint32_t)); - size_t BindingSize = (Version < 2) ? sizeof(v0::ResourceBindInfo) - : sizeof(v2::ResourceBindInfo); + OS.write(reinterpret_cast(&BindingSize), sizeof(uint32_t)); for (const auto &Res : Resources) OS.write(reinterpret_cast(&Res), BindingSize); } diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp --- a/llvm/lib/Object/DXContainer.cpp +++ b/llvm/lib/Object/DXContainer.cpp @@ -200,6 +200,10 @@ StringRef PSVInfoData = Data.substr(sizeof(uint32_t), Size); + if (PSVInfoData.size() < Size) + return parseFailed( + "Pipeline state data extends beyond the bounds of the part"); + using namespace dxbc::PSV; const uint32_t PSVVersion = getVersion(); @@ -234,12 +238,20 @@ return Err; Current += sizeof(uint32_t); - Resources.Stride = (PSVVersion < 2) ? sizeof(v0::ResourceBindInfo) - : sizeof(v2::ResourceBindInfo); - size_t BindingDataSize = Resources.Stride * ResourceCount; - Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize); + if (ResourceCount > 0) { + if (Error Err = readInteger(Data, Current, Resources.Stride)) + return Err; + Current += sizeof(uint32_t); + + size_t BindingDataSize = Resources.Stride * ResourceCount; + Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize); - Current += BindingDataSize; + if (Resources.Data.size() < BindingDataSize) + return parseFailed( + "Resource binding data extends beyond the bounds of the part"); + + Current += BindingDataSize; + } return Error::success(); } diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -127,6 +127,7 @@ IO.mapRequired("ShaderStage", PSV.Info.ShaderStage); PSV.mapInfoForVersion(IO); + IO.mapRequired("ResourceStride", PSV.ResourceStride); IO.mapRequired("Resources", PSV.Resources); // Restore the YAML context. diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml @@ -17,6 +17,7 @@ PayloadSizeInBytes: 4092 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -45,6 +46,7 @@ # CHECK-NEXT: PayloadSizeInBytes: 4092 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml @@ -16,6 +16,7 @@ ShaderStage: 5 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -43,6 +44,7 @@ # CHECK-NEXT: ShaderStage: 5 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml @@ -19,6 +19,7 @@ TessellatorDomain: 2056 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -49,6 +50,7 @@ # CHECK-NEXT: TessellatorDomain: 2056 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml @@ -20,6 +20,7 @@ OutputPositionPresent: 1 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -51,6 +52,7 @@ # CHECK-NEXT: OutputPositionPresent: 1 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml @@ -20,6 +20,7 @@ TessellatorOutputPrimitive: 8192 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -51,6 +52,7 @@ # CHECK-NEXT: TessellatorOutputPrimitive: 8192 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml @@ -21,6 +21,7 @@ MaxOutputPrimitives: 4092 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -53,6 +54,7 @@ # CHECK-NEXT: MaxOutputPrimitives: 4092 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml @@ -18,6 +18,7 @@ SampleFrequency: 96 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -47,6 +48,7 @@ # CHECK-NEXT: SampleFrequency: 96 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml @@ -17,6 +17,7 @@ OutputPositionPresent: 1 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -45,6 +46,7 @@ # CHECK-NEXT: OutputPositionPresent: 1 # CHECK-NEXT: MinimumWaveLaneCount: 0 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml @@ -23,6 +23,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -57,6 +58,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml @@ -22,6 +22,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -55,6 +56,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml @@ -26,6 +26,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -63,6 +64,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml @@ -27,6 +27,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -65,6 +66,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml @@ -27,6 +27,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -65,6 +66,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml @@ -29,6 +29,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -69,6 +70,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml @@ -24,6 +24,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -59,6 +60,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml @@ -23,6 +23,7 @@ SigPatchConstOrPrimElements: 32 SigInputVectors: 64 SigOutputVectors: [ 8, 16, 32, 64 ] + ResourceStride: 16 Resources: - Type: 1 Space: 2 @@ -57,6 +58,7 @@ # CHECK-NEXT: SigPatchConstOrPrimElements: 32 # CHECK-NEXT: SigInputVectors: 64 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: ResourceStride: 16 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml @@ -26,6 +26,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -67,6 +68,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml @@ -25,6 +25,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -65,6 +66,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml @@ -29,6 +29,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -73,6 +74,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml @@ -30,6 +30,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -75,6 +76,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml @@ -30,6 +30,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -75,6 +76,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml @@ -32,6 +32,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -79,6 +80,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml @@ -27,6 +27,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -69,6 +70,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml --- a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml +++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml @@ -26,6 +26,7 @@ NumThreadsX: 512 NumThreadsY: 1024 NumThreadsZ: 2048 + ResourceStride: 24 Resources: - Type: 1 Space: 2 @@ -67,6 +68,7 @@ # CHECK-NEXT: NumThreadsX: 512 # CHECK-NEXT: NumThreadsY: 1024 # CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: ResourceStride: 24 # CHECK-NEXT: Resources: # CHECK-NEXT: - Type: 1 # CHECK-NEXT: Space: 2 diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp --- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp +++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp @@ -89,6 +89,7 @@ else if (const auto *P = std::get_if(&PSVInfo->getInfo())) NewPart.Info = DXContainerYAML::PSVInfo(P); + NewPart.Info->ResourceStride = PSVInfo->getResourceStride(); for (auto Res : PSVInfo->getResources()) NewPart.Info->Resources.push_back(Res); break; diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -219,6 +219,7 @@ PayloadSizeInBytes: 4092 MinimumWaveLaneCount: 0 MaximumWaveLaneCount: 4294967295 + ResourceStride: 16 Resources: - Type: 1 Space: 1 @@ -334,9 +335,261 @@ 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); +}