blob: 51adc2b4c3718d65fbb3ead33c39337b6cb929f7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// slang-check-out-of-bound-access.cpp
#include "slang-check-out-of-bound-access.h"
#include "slang-ir-inst-pass-base.h"
#include "slang-ir-insts.h"
#include "slang-ir.h"
namespace Slang
{
struct OutOfBoundAccessChecker : public InstPassBase
{
DiagnosticSink* sink;
OutOfBoundAccessChecker(IRModule* inModule, DiagnosticSink* inSink)
: InstPassBase(inModule), sink(inSink)
{
}
void checkArrayAccess(IRInst* inst, IRInst* base, IRInst* index)
{
// Check if index is a constant integer
auto indexLit = as<IRIntLit>(index);
if (!indexLit)
return; // Skip non-constant indices
// Get the base type
auto baseType = base->getDataType();
// Handle pointer-to-array case (for GetElementPtr)
if (auto ptrType = as<IRPtrTypeBase>(baseType))
{
baseType = ptrType->getValueType();
}
// Check if base is an array type
auto arrayType = as<IRArrayTypeBase>(baseType);
if (!arrayType)
return; // Skip non-array types
// Check if array size is a constant
auto arraySizeInst = arrayType->getElementCount();
auto arraySizeLit = as<IRIntLit>(arraySizeInst);
if (!arraySizeLit)
return; // Skip arrays with non-constant size
// Get the actual values
IRIntegerValue indexValue = indexLit->getValue();
IRIntegerValue arraySizeValue = arraySizeLit->getValue();
// Check bounds: index should be >= 0 and < arraySize
if (indexValue < 0 || indexValue >= arraySizeValue)
{
sink->diagnose(inst, Diagnostics::arrayIndexOutOfBounds, indexValue, arraySizeValue);
}
}
void processModule()
{
processAllInsts(
[&](IRInst* inst)
{
switch (inst->getOp())
{
case kIROp_GetElement:
case kIROp_GetElementPtr:
{
if (inst->getOperandCount() < 2)
return;
auto base = inst->getOperand(0);
auto index = inst->getOperand(1);
checkArrayAccess(inst, base, index);
}
break;
}
});
}
};
void checkForOutOfBoundAccess(IRModule* module, DiagnosticSink* sink)
{
OutOfBoundAccessChecker checker(module, sink);
checker.processModule();
}
} // namespace Slang
|