diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index d426b955f2..58977360ca 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -39,6 +39,7 @@ line upon naming the release. Refer to previous for appropriate section names. #### Other Changes - Fixed mesh shader semantics that were incorrectly case sensitive. +- DXIL validation: added index range validation for `CreateHandleFromBinding` to match existing `CreateHandle` validation. ### Version 1.9.2602 diff --git a/lib/DxilValidation/DxilValidationUtils.cpp b/lib/DxilValidation/DxilValidationUtils.cpp index f0f85fcd26..28a8250b1d 100644 --- a/lib/DxilValidation/DxilValidationUtils.cpp +++ b/lib/DxilValidation/DxilValidationUtils.cpp @@ -15,6 +15,7 @@ #include "dxc/DXIL/DxilInstructions.h" #include "dxc/DXIL/DxilModule.h" #include "dxc/DXIL/DxilOperations.h" +#include "dxc/DXIL/DxilResourceBinding.h" #include "dxc/DXIL/DxilUtil.h" #include "dxc/Support/Global.h" @@ -229,6 +230,30 @@ void ValidationContext::BuildResMap() { } const ShaderModel &SM = *DxilMod.GetShaderModel(); + // Scan all createHandleFromBinding for index validation. + for (auto &it : + hlslOP->GetOpFuncList(DXIL::OpCode::CreateHandleFromBinding)) { + Function *F = it.second; + if (!F) + continue; + for (User *U : F->users()) { + CallInst *CI = cast(U); + DxilInst_CreateHandleFromBinding hdl(CI); + ConstantInt *cIndex = dyn_cast(hdl.get_index()); + if (cIndex) { + DxilResourceBinding B = + resource_helper::loadBindingFromCreateHandleFromBinding( + hdl, hlslOP->GetHandleType(), SM); + unsigned index = cIndex->getLimitedValue(); + if (index < B.rangeLowerBound || index > B.rangeUpperBound) { + // index out of range. + EmitInstrError(CI, ValidationRule::InstrOpConstRange); + continue; + } + } + } + } + for (auto &it : hlslOP->GetOpFuncList(DXIL::OpCode::AnnotateHandle)) { Function *F = it.second; if (!F) diff --git a/tools/clang/test/LitDXILValidation/createHandleFromBinding-index-out-of-range.ll b/tools/clang/test/LitDXILValidation/createHandleFromBinding-index-out-of-range.ll new file mode 100644 index 0000000000..b1b86acd4b --- /dev/null +++ b/tools/clang/test/LitDXILValidation/createHandleFromBinding-index-out-of-range.ll @@ -0,0 +1,50 @@ +; REQUIRES: dxil-1-8 +; RUN: not %dxv %s 2>&1 | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.ResBind = type { i32, i32, i32, i8 } +%dx.types.ResourceProperties = type { i32, i32 } +%struct.RWByteAddressBuffer = type { i32 } + +; CHECK-DAG: error: Constant values must be in-range for operation. +; CHECK-DAG: note: at '%1 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 3, i32 0, i8 1 }, i32 0, i1 false)' in block '#0' of function 'main'. +; CHECK-DAG: error: Constant values must be in-range for operation. +; CHECK-DAG: note: at '%3 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 3, i32 0, i8 1 }, i32 4, i1 false)' in block '#0' of function 'main'. + +define void @main() { + ; Binding has rangeLowerBound=1, rangeUpperBound=3, but index is 0 (below lower bound) + %1 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 3, i32 0, i8 1 }, i32 0, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 4107, i32 0 }) ; AnnotateHandle(res,props) resource: RWByteAddressBuffer + ; Binding has rangeLowerBound=1, rangeUpperBound=3, but index is 4 (above upper bound) + %3 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 3, i32 0, i8 1 }, i32 4, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex) + %4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 4107, i32 0 }) ; AnnotateHandle(res,props) resource: RWByteAddressBuffer + ret void +} + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #0 + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @dx.op.createHandleFromBinding(i32, %dx.types.ResBind, i32, i1) #0 + +attributes #0 = { nounwind readnone } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!1} +!dx.shaderModel = !{!2} +!dx.resources = !{!3} +!dx.entryPoints = !{!6} + +!0 = !{!"dxc(private) 1.8.0.15017 (main, 4e0f5364a-dirty)"} +!1 = !{i32 1, i32 8} +!2 = !{!"cs", i32 6, i32 8} +!3 = !{null, !4, null, null} +!4 = !{!5} +!5 = !{i32 0, %struct.RWByteAddressBuffer* undef, !"", i32 0, i32 1, i32 3, i32 11, i1 false, i1 false, i1 false, null} +!6 = !{void ()* @main, !"main", null, !3, !7} +!7 = !{i32 0, i64 8589934608, i32 4, !8} +!8 = !{i32 4, i32 1, i32 1}