Skip to content

Commit 9de9f03

Browse files
authored
[SemaHLSL] Correct descriptor range overflow validation (#159475)
This pr corrects the validation behaviour to allow valid root signatures of the form: `DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1))` which will append a range onto the location of `UINT_MAX`, which is valid. Resolves: #159478.
1 parent 4a9df48 commit 9de9f03

File tree

5 files changed

+28
-25
lines changed

5 files changed

+28
-25
lines changed

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,8 @@ bool SemaHLSL::handleRootSignatureElements(
13691369
"Number of unbound elements must match the number of clauses");
13701370
bool HasAnySampler = false;
13711371
bool HasAnyNonSampler = false;
1372-
uint32_t Offset = 0;
1372+
uint64_t Offset = 0;
1373+
bool IsPrevUnbound = false;
13731374
for (const auto &[Clause, ClauseElem] : UnboundClauses) {
13741375
SourceLocation Loc = ClauseElem->getLocation();
13751376
if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
@@ -1386,32 +1387,28 @@ bool SemaHLSL::handleRootSignatureElements(
13861387
if (Clause->NumDescriptors == 0)
13871388
return true;
13881389

1389-
if (Clause->Offset !=
1390-
llvm::hlsl::rootsig::DescriptorTableOffsetAppend) {
1391-
// Manually specified the offset
1390+
bool IsAppending =
1391+
Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1392+
if (!IsAppending)
13921393
Offset = Clause->Offset;
1393-
}
13941394

13951395
uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
13961396
Offset, Clause->NumDescriptors);
13971397

1398-
if (!llvm::hlsl::rootsig::verifyBoundOffset(Offset)) {
1399-
// Trying to append onto unbound offset
1398+
if (IsPrevUnbound && IsAppending)
14001399
Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1401-
} else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) {
1402-
// Upper bound overflows maximum offset
1400+
else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
14031401
Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1404-
}
14051402

1406-
Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded
1407-
? uint32_t(RangeBound)
1408-
: uint32_t(RangeBound + 1);
1403+
// Update offset to be 1 past this range's bound
1404+
Offset = RangeBound + 1;
1405+
IsPrevUnbound = Clause->NumDescriptors ==
1406+
llvm::hlsl::rootsig::NumDescriptorsUnbounded;
14091407

14101408
// Compute the register bounds and track resource binding
14111409
uint32_t LowerBound(Clause->Reg.Number);
1412-
uint32_t UpperBound = Clause->NumDescriptors == ~0u
1413-
? ~0u
1414-
: LowerBound + Clause->NumDescriptors - 1;
1410+
uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1411+
LowerBound, Clause->NumDescriptors);
14151412

14161413
BindingChecker.trackBinding(
14171414
Table->Visibility,

clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,12 @@ void append_offset_overflow_signature() {}
141141

142142
// expected-error@+1 {{descriptor range offset overflows [4294967292, 4294967296]}}
143143
[RootSignature("DescriptorTable(CBV(b0, offset = 4294967292, numDescriptors = 5))")]
144-
void offset_() {}
144+
void offset_overflow() {}
145+
146+
// expected-error@+1 {{descriptor range offset overflows [4294967295, 4294967296]}}
147+
[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1, numDescriptors = 2))")]
148+
void appended_offset_overflow() {}
149+
150+
// expected-error@+1 {{descriptor range offset overflows [4294967296, 4294967296]}}
151+
[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1), CBV(b2))")]
152+
void multiple_appended_offset_overflow() {}

clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ void valid_root_signature_6() {}
2525

2626
[RootSignature("DescriptorTable(CBV(b0, offset = 4294967292), CBV(b1, numDescriptors = 3))")]
2727
void valid_root_signature_7() {}
28+
29+
[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1))")]
30+
void valid_root_signature_8() {}

llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ LLVM_ABI bool verifyMipLODBias(float MipLODBias);
3838
LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
3939
LLVM_ABI bool verifyLOD(float LOD);
4040

41-
LLVM_ABI bool verifyBoundOffset(uint32_t Offset);
4241
LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset);
43-
LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size);
42+
LLVM_ABI uint64_t computeRangeBound(uint64_t Offset, uint32_t Size);
4443

4544
} // namespace rootsig
4645
} // namespace hlsl

llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,16 @@ bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) {
125125

126126
bool verifyLOD(float LOD) { return !std::isnan(LOD); }
127127

128-
bool verifyBoundOffset(uint32_t Offset) {
129-
return Offset != NumDescriptorsUnbounded;
130-
}
131-
132128
bool verifyNoOverflowedOffset(uint64_t Offset) {
133129
return Offset <= std::numeric_limits<uint32_t>::max();
134130
}
135131

136-
uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) {
132+
uint64_t computeRangeBound(uint64_t Offset, uint32_t Size) {
137133
assert(0 < Size && "Must be a non-empty range");
138134
if (Size == NumDescriptorsUnbounded)
139135
return NumDescriptorsUnbounded;
140136

141-
return uint64_t(Offset) + uint64_t(Size) - 1;
137+
return Offset + uint64_t(Size) - 1;
142138
}
143139

144140
} // namespace rootsig

0 commit comments

Comments
 (0)