Skip to content

Commit 64cf090

Browse files
committed
Address review.
Most important fix is that VNLength is now restricted to the subset of value numbers that are Bounds in the RangeAnalysis.
1 parent 9d2533c commit 64cf090

3 files changed

Lines changed: 27 additions & 16 deletions

File tree

cpp/ql/src/experimental/library/ArrayLengthAnalysis.qll

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,39 @@ private import semmle.code.cpp.rangeanalysis.RangeUtils
2525
private newtype TLength =
2626
TZeroLength() or
2727
TVNLength(ValueNumber vn) {
28+
not vn.getAnInstruction() instanceof ConstantInstruction and
2829
exists(Instruction i |
2930
vn.getAnInstruction() = i and
3031
(
3132
i.getResultIRType() instanceof IRSignedIntegerType or
3233
i.getResultIRType() instanceof IRUnsignedIntegerType
3334
)
34-
) and
35-
not vn.getAnInstruction() instanceof ConstantInstruction
35+
|
36+
i instanceof PhiInstruction
37+
or
38+
i instanceof InitializeParameterInstruction
39+
or
40+
i instanceof CallInstruction
41+
or
42+
i instanceof VariableAddressInstruction
43+
or
44+
i instanceof FieldAddressInstruction
45+
or
46+
i.(LoadInstruction).getSourceAddress() instanceof VariableAddressInstruction
47+
or
48+
i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction
49+
or
50+
i.getAUse() instanceof ArgumentOperand
51+
)
3652
}
3753

3854
/**
3955
* Array lengths are represented in a ValueNumber | Zero + delta format.
4056
* This class keeps track of the ValueNumber or Zero.
4157
* The delta is tracked in the predicate `knownArrayLength`.
4258
*/
43-
abstract class Length extends TLength {
44-
abstract string toString();
59+
class Length extends TLength {
60+
string toString() { none() } // overridden in subclasses
4561
}
4662

4763
/**
@@ -62,7 +78,7 @@ class VNLength extends Length, TVNLength {
6278

6379
VNLength() { this = TVNLength(vn) }
6480

65-
/** Gets the SSA variable that equals value number bound. */
81+
/** Gets an instruction with this value number bound. */
6682
Instruction getInstruction() { this = TVNLength(valueNumber(result)) }
6783

6884
ValueNumber getValueNumber() { result = vn }
@@ -81,8 +97,8 @@ private newtype TOffset =
8197
* This class describes the offset of a pointer in a chunk of memory.
8298
* It is either an `Operand` or zero, an additional integer delta is added later.
8399
*/
84-
abstract class Offset extends TOffset {
85-
abstract string toString();
100+
class Offset extends TOffset {
101+
string toString() { none() } // overridden in subclasses
86102
}
87103

88104
/**
@@ -203,12 +219,10 @@ private predicate allocation(Instruction array, Length length, int delta) {
203219
(
204220
exists(Expr lengthExpr |
205221
deconstructMallocSizeExpr(alloc.getSizeExpr(), lengthExpr, delta) and
206-
// TODO converted or unconverted here?
207222
length.(VNLength).getInstruction().getConvertedResultExpression() = lengthExpr
208223
)
209224
or
210225
not exists(int d | deconstructMallocSizeExpr(alloc.getSizeExpr(), _, d)) and
211-
// TODO converted or unconverted here?
212226
length.(VNLength).getInstruction().getConvertedResultExpression() = alloc.getSizeExpr() and
213227
delta = 0
214228
)
@@ -245,14 +259,13 @@ predicate arrayAllocationOrDeclaration(Instruction array, Length length, int len
245259
* Holds if the instruction `array` represents a pointer to a chunk of memory that holds
246260
* `length + lengthDelta` elements, using only local analysis.
247261
* `array` points at `offset + offsetDelta` in the chunk of memory.
248-
* The pointer is in-bounds if `offset < length + lengthDelta` and
262+
* The pointer is in-bounds if `offset + offsetDelta < length + lengthDelta` and
249263
* `offset + offsetDelta >= 0` holds.
250-
* The pointer is out-of-bounds if `offset >= length + lengthDelta`
264+
* The pointer is out-of-bounds if `offset + offsetDelta >= length + lengthDelta`
251265
* or `offset + offsetDelta < 0` holds.
252266
* All pointers in this predicate are guaranteed to be non-null,
253267
* but are not guaranteed to be live.
254268
*/
255-
cached
256269
predicate knownArrayLength(
257270
Instruction array, Length length, int lengthDelta, Offset offset, int offsetDelta
258271
) {

cpp/ql/test/experimental/library-tests/arraylengthanalysis/ArrayLengthAnalysisTest.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
| test.cpp:19:8:19:8 | Load: a | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
33
| test.cpp:21:8:21:8 | Load: a | VNLength(Chi: ptr) | -1 | ZeroOffset | 0 |
44
| test.cpp:23:8:23:8 | Load: a | VNLength(Chi: ptr) | 1 | ZeroOffset | 0 |
5-
| test.cpp:25:8:25:8 | Load: a | VNLength(Mul: ... * ...) | 0 | ZeroOffset | 0 |
65
| test.cpp:27:8:27:8 | Load: c | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
76
| test.cpp:28:8:28:24 | Convert: (unsigned char *)... | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
87
| test.cpp:30:8:30:8 | Load: v | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
@@ -22,4 +21,3 @@
2221
| test.cpp:80:8:80:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Load: count) | 1 |
2322
| test.cpp:85:8:85:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 0 |
2423
| test.cpp:87:8:87:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 1 |
25-
| test.cpp:89:8:89:8 | Load: a | VNLength(Sub: ... - ...) | 0 | ZeroOffset | 0 |

cpp/ql/test/experimental/library-tests/arraylengthanalysis/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void test1(unsigned int count) {
2222
a = (int *) malloc(sizeof(int) * (count + 1));
2323
sink(a); // (count, 1, Zero, 0)
2424
a = (int *) malloc(sizeof(int) * (2 * count));
25-
sink(a); // (2*count, 0, Zero, 0)
25+
sink(a); // none, as the size expression is too complicated
2626
char* c = (char *)malloc(count);
2727
sink(c); // /count, 0, Zero, 0)
2828
sink((unsigned char*)c); // (count, 0, Zero, 0)
@@ -86,5 +86,5 @@ void test2(unsigned int count, bool b) {
8686
a += 1;
8787
sink(a); // TODO, should be (count, 1, count, 2), but is (count, 1, count + 1, 1)
8888
a = (int*) malloc(sizeof(int) * (1024 - count));
89-
sink(a); // (1024-count, 0, Zero, 0)
89+
sink(a); // none, as the size expression is too complicated
9090
}

0 commit comments

Comments
 (0)