Skip to content

Commit 43a5855

Browse files
Add Check for WordCount Against SPIRV File Size (#3266)
A check is inserted in `parseAndCreateSPIRVEntry` function to ensure the `WordCount` for the current SPIR-V instruction is not smaller than the remaining input stream size. If the stream does not contain enough data for the specified `WordCount`, an SPIRV error of `InvalidWordCount` is raised.
1 parent 8e82970 commit 43a5855

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2088,7 +2088,10 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
20882088
<< "have (" << MaxNumElements << "). Should the array be "
20892089
<< "split?\n Original LLVM value:\n"
20902090
<< toString(GV);
2091-
getErrorLog().checkError(false, SPIRVEC_InvalidWordCount, SS.str());
2091+
getErrorLog().checkError(false, SPIRVEC_InvalidWordCount,
2092+
"Can't encode instruction with word count "
2093+
"greater than 65535:\n" +
2094+
SS.str());
20922095
}
20932096
}
20942097
}

lib/SPIRV/libSPIRV/SPIRVEntry.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,10 @@ class SPIRVEntry {
412412
std::stringstream SS;
413413
SS << "Id: " << Id << ", OpCode: " << OpCodeNameMap::map(OpCode)
414414
<< ", Name: \"" << Name << "\"\n";
415-
getErrorLog().checkError(false, SPIRVEC_InvalidWordCount, SS.str());
415+
getErrorLog().checkError(
416+
false, SPIRVEC_InvalidWordCount,
417+
"Can't encode instruction with word count greater than 65535:\n" +
418+
SS.str());
416419
}
417420
}
418421
void validateFunctionControlMask(SPIRVWord FCtlMask) const;

lib/SPIRV/libSPIRV/SPIRVErrorEnum.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ _SPIRV_OP(InvalidLlvmModule, "Invalid LLVM module:")
1616
_SPIRV_OP(UnimplementedOpCode, "Unimplemented opcode")
1717
_SPIRV_OP(FunctionPointers, "Can't translate function pointer:\n")
1818
_SPIRV_OP(InvalidInstruction, "Can't translate llvm instruction:\n")
19-
_SPIRV_OP(InvalidWordCount,
20-
"Can't encode instruction with word count greater than 65535:\n")
19+
_SPIRV_OP(InvalidWordCount, "")
2120
_SPIRV_OP(Requires1_1, "Feature requires SPIR-V 1.1 or greater:")
2221
_SPIRV_OP(RequiresVersion, "Cannot fulfill SPIR-V version restriction:\n")
2322
_SPIRV_OP(RequiresExtension,

lib/SPIRV/libSPIRV/SPIRVModule.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,23 @@ SPIRVEntry *parseAndCreateSPIRVEntry(SPIRVWord &WordCount, Op &OpCode,
23852385
if (WordCount == 0 || OpCode == OpNop) {
23862386
return nullptr;
23872387
}
2388+
if (!SPIRVUseTextFormat) {
2389+
std::streampos CurrentPos = IS.tellg();
2390+
IS.seekg(0, std::ios::end);
2391+
std::streamoff RemainingBytes = IS.tellg() - CurrentPos;
2392+
IS.clear();
2393+
IS.seekg(CurrentPos);
2394+
std::streamoff ExpectedBytes =
2395+
static_cast<std::streamoff>((WordCount - 1) * sizeof(SPIRVWord));
2396+
if (RemainingBytes < ExpectedBytes) {
2397+
M.getErrorLog().checkError(
2398+
false, SPIRVEC_InvalidWordCount,
2399+
"WordCount exceeds remaining input stream size: expected size = " +
2400+
std::to_string(ExpectedBytes) + " bytes, remaining size = " +
2401+
std::to_string(RemainingBytes) + " bytes");
2402+
M.setInvalid();
2403+
}
2404+
}
23882405
SPIRVEntry *Entry = SPIRVEntry::create(OpCode);
23892406
assert(Entry);
23902407
Entry->setModule(&M);

0 commit comments

Comments
 (0)