Skip to content

Commit c6e9fea

Browse files
authored
Fix of ParentIdx mismatch for DebugTypeInheritance in SPIRV.debug.h (#2490)
Fixed ParentIdx was mismatched for DebugTypeInheritance type in context of NonSemantic.Shader.DebugInfo.100. That lead to heap buffer overflow in SPIRVExtInst::getExtOp getter when instruction was incorrectly casted to SPIRVExtInst as parent of the culprit instruction in SPIRVToLLVMDbgTran::getDIBuilder. The missmatch happen because in previous used standard OpenCL.DebugInfo.100 DebugTypeInheritance had Child field as zero indexed argument. In newer standard that field is removed.
1 parent 0d83f22 commit c6e9fea

File tree

3 files changed

+72
-30
lines changed

3 files changed

+72
-30
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
//
3737
//===----------------------------------------------------------------------===//
3838
#include "LLVMToSPIRVDbgTran.h"
39+
#include "SPIRV.debug.h"
3940
#include "SPIRVWriter.h"
4041

4142
#include "llvm/IR/DebugInfo.h"
@@ -1052,20 +1053,32 @@ LLVMToSPIRVDbgTran::transDbgMemberTypeNonSemantic(const DIDerivedType *MT) {
10521053

10531054
SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) {
10541055
using namespace SPIRVDebug::Operand::TypeInheritance;
1055-
const SPIRVWord Offset = isNonSemanticDebugInfo() ? 1 : 0;
1056-
SPIRVWordVec Ops(OperandCount - Offset);
1057-
// There is no Child operand in NonSemantic debug spec
1058-
if (!isNonSemanticDebugInfo())
1059-
Ops[ChildIdx] = transDbgEntry(DT->getScope())->getId();
1060-
Ops[ParentIdx - Offset] = transDbgEntry(DT->getBaseType())->getId();
1056+
unsigned ParentIdx, OffsetIdx, SizeIdx, FlagsIdx, OperandCount;
1057+
if (isNonSemanticDebugInfo()) {
1058+
ParentIdx = NonSemantic::ParentIdx;
1059+
OffsetIdx = NonSemantic::OffsetIdx;
1060+
SizeIdx = NonSemantic::SizeIdx;
1061+
FlagsIdx = NonSemantic::FlagsIdx;
1062+
OperandCount = NonSemantic::OperandCount;
1063+
} else {
1064+
ParentIdx = OpenCL::ParentIdx;
1065+
OffsetIdx = OpenCL::OffsetIdx;
1066+
SizeIdx = OpenCL::SizeIdx;
1067+
FlagsIdx = OpenCL::FlagsIdx;
1068+
OperandCount = OpenCL::OperandCount;
1069+
}
1070+
SPIRVWordVec Ops(OperandCount);
1071+
Ops[ParentIdx] = transDbgEntry(DT->getBaseType())->getId();
10611072
ConstantInt *OffsetInBits = getUInt(M, DT->getOffsetInBits());
1062-
Ops[OffsetIdx - Offset] =
1063-
SPIRVWriter->transValue(OffsetInBits, nullptr)->getId();
1073+
Ops[OffsetIdx] = SPIRVWriter->transValue(OffsetInBits, nullptr)->getId();
10641074
ConstantInt *Size = getUInt(M, DT->getSizeInBits());
1065-
Ops[SizeIdx - Offset] = SPIRVWriter->transValue(Size, nullptr)->getId();
1066-
Ops[FlagsIdx - Offset] = transDebugFlags(DT);
1067-
if (isNonSemanticDebugInfo())
1068-
transformToConstant(Ops, {FlagsIdx - Offset});
1075+
Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId();
1076+
Ops[FlagsIdx] = transDebugFlags(DT);
1077+
if (isNonSemanticDebugInfo()) {
1078+
transformToConstant(Ops, {FlagsIdx});
1079+
} else {
1080+
Ops[OpenCL::ChildIdx] = transDbgEntry(DT->getScope())->getId();
1081+
}
10691082
return BM->addDebugInfo(SPIRVDebug::TypeInheritance, getVoidTy(), Ops);
10701083
}
10711084

lib/SPIRV/SPIRVToLLVMDbgTran.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
//===----------------------------------------------------------------------===//
3838

3939
#include "SPIRVToLLVMDbgTran.h"
40+
#include "SPIRV.debug.h"
4041
#include "SPIRVEntry.h"
4142
#include "SPIRVFunction.h"
4243
#include "SPIRVInstruction.h"
@@ -1214,32 +1215,47 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) {
12141215

12151216
DINode *SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst,
12161217
DIType *ChildClass) {
1217-
if (isNonSemanticDebugInfo(DebugInst->getExtSetKind()) && !ChildClass) {
1218-
// Will be translated later when processing TypeMember's parent
1219-
return nullptr;
1220-
}
12211218
using namespace SPIRVDebug::Operand::TypeInheritance;
1219+
// The value is used when assertions are enabled
1220+
[[maybe_unused]] unsigned OperandCount;
1221+
unsigned ParentIdx, OffsetIdx, FlagsIdx;
1222+
if (isNonSemanticDebugInfo(DebugInst->getExtSetKind())) {
1223+
if (!ChildClass) {
1224+
// Will be translated later when processing TypeMember's parent
1225+
return nullptr;
1226+
}
1227+
OperandCount = NonSemantic::OperandCount;
1228+
ParentIdx = NonSemantic::ParentIdx;
1229+
OffsetIdx = NonSemantic::OffsetIdx;
1230+
FlagsIdx = NonSemantic::FlagsIdx;
1231+
} else {
1232+
OperandCount = NonSemantic::OperandCount;
1233+
ParentIdx = OpenCL::ParentIdx;
1234+
OffsetIdx = OpenCL::OffsetIdx;
1235+
FlagsIdx = OpenCL::FlagsIdx;
1236+
}
12221237
const SPIRVWordVec &Ops = DebugInst->getArguments();
1223-
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
1224-
// No Child operand for NonSemantic debug spec
1225-
SPIRVWord Offset = isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ? 1 : 0;
1238+
assert(Ops.size() >= OperandCount && "Invalid number of operands");
12261239
DIType *Parent =
1227-
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[ParentIdx - Offset]));
1228-
DIType *Child =
1229-
isNonSemanticDebugInfo(DebugInst->getExtSetKind())
1230-
? ChildClass
1231-
: transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[ChildIdx]));
1240+
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[ParentIdx]));
12321241
DINode::DIFlags Flags = DINode::FlagZero;
1233-
SPIRVWord SPIRVFlags = getConstantValueOrLiteral(Ops, FlagsIdx - Offset,
1234-
DebugInst->getExtSetKind());
1242+
SPIRVWord SPIRVFlags =
1243+
getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
12351244
if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic)
12361245
Flags |= llvm::DINode::FlagPublic;
12371246
if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected)
12381247
Flags |= llvm::DINode::FlagProtected;
12391248
if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate)
12401249
Flags |= llvm::DINode::FlagPrivate;
12411250
uint64_t OffsetVal =
1242-
BM->get<SPIRVConstant>(Ops[OffsetIdx - Offset])->getZExtIntValue();
1251+
BM->get<SPIRVConstant>(Ops[OffsetIdx])->getZExtIntValue();
1252+
DIType *Child;
1253+
if (isNonSemanticDebugInfo(DebugInst->getExtSetKind())) {
1254+
Child = ChildClass;
1255+
} else {
1256+
Child =
1257+
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[OpenCL::ChildIdx]));
1258+
}
12431259
return getDIBuilder(DebugInst).createInheritance(Child, Parent, OffsetVal, 0,
12441260
Flags);
12451261
}

lib/SPIRV/libSPIRV/SPIRV.debug.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,17 +503,27 @@ enum {
503503
} // namespace TypeMember
504504

505505
namespace TypeInheritance {
506+
namespace NonSemantic {
507+
enum {
508+
ParentIdx = 0,
509+
OffsetIdx = 1,
510+
SizeIdx = 2,
511+
FlagsIdx = 3,
512+
OperandCount = 4
513+
};
514+
}
515+
516+
namespace OpenCL {
506517
enum {
507518
ChildIdx = 0,
508519
ParentIdx = 1,
509520
OffsetIdx = 2,
510521
SizeIdx = 3,
511522
FlagsIdx = 4,
512-
// NonSemantic
513-
MinOperandCount = 4,
514523
OperandCount = 5
515524
};
516525
}
526+
} // namespace TypeInheritance
517527

518528
namespace TypePtrToMember {
519529
enum {
@@ -991,7 +1001,10 @@ inline bool hasDbgInstParentScopeIdx(
9911001
ParentScopeIdx = TypeMember::OpenCL::ParentIdx;
9921002
return true;
9931003
case SPIRVDebug::TypeInheritance:
994-
ParentScopeIdx = TypeInheritance::ParentIdx;
1004+
if (ExtKind == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100)
1005+
ParentScopeIdx = TypeInheritance::OpenCL::ParentIdx;
1006+
else
1007+
ParentScopeIdx = TypeInheritance::NonSemantic::ParentIdx;
9951008
return true;
9961009
case SPIRVDebug::TypePtrToMember:
9971010
ParentScopeIdx = TypePtrToMember::ParentIdx;

0 commit comments

Comments
 (0)