@@ -25,16 +25,23 @@ Instruction getABoundIn(SemBound b, IRFunction func) {
25
25
/**
26
26
* Holds if `i <= b + delta`.
27
27
*/
28
- bindingset [ i]
29
- pragma [ inline_late]
30
- predicate bounded ( Instruction i , Instruction b , int delta ) {
28
+ pragma [ inline]
29
+ predicate boundedImpl ( Instruction i , Instruction b , int delta ) {
31
30
exists ( SemBound bound , IRFunction func |
32
31
semBounded ( getSemanticExpr ( i ) , bound , delta , true , _) and
33
32
b = getABoundIn ( bound , func ) and
34
- i .getEnclosingIRFunction ( ) = func
33
+ pragma [ only_bind_out ] ( i .getEnclosingIRFunction ( ) ) = func
35
34
)
36
35
}
37
36
37
+ bindingset [ i]
38
+ pragma [ inline_late]
39
+ predicate bounded1 ( Instruction i , Instruction b , int delta ) { boundedImpl ( i , b , delta ) }
40
+
41
+ bindingset [ b]
42
+ pragma [ inline_late]
43
+ predicate bounded2 ( Instruction i , Instruction b , int delta ) { boundedImpl ( i , b , delta ) }
44
+
38
45
module FieldAddressToPointerArithmeticConfig implements DataFlow:: ConfigSig {
39
46
predicate isSource ( DataFlow:: Node source ) { isFieldAddressSource ( _, source ) }
40
47
@@ -50,23 +57,39 @@ predicate isFieldAddressSource(Field f, DataFlow::Node source) {
50
57
source .asInstruction ( ) .( FieldAddressInstruction ) .getField ( ) = f
51
58
}
52
59
60
+ bindingset [ delta]
61
+ predicate isInvalidPointerDerefSinkImpl (
62
+ int delta , Instruction i , AddressOperand addr , string operation
63
+ ) {
64
+ delta >= 0 and
65
+ i .getAnOperand ( ) = addr and
66
+ (
67
+ i instanceof StoreInstruction and
68
+ operation = "write"
69
+ or
70
+ i instanceof LoadInstruction and
71
+ operation = "read"
72
+ )
73
+ }
74
+
53
75
/**
54
76
* Holds if `sink` is a sink for `InvalidPointerToDerefConf` and `i` is a `StoreInstruction` that
55
77
* writes to an address that non-strictly upper-bounds `sink`, or `i` is a `LoadInstruction` that
56
78
* reads from an address that non-strictly upper-bounds `sink`.
57
79
*/
58
80
pragma [ inline]
59
- predicate isInvalidPointerDerefSink ( DataFlow:: Node sink , Instruction i , string operation ) {
81
+ predicate isInvalidPointerDerefSink1 ( DataFlow:: Node sink , Instruction i , string operation ) {
60
82
exists ( AddressOperand addr , int delta |
61
- bounded ( addr .getDef ( ) , sink .asInstruction ( ) , delta ) and
62
- delta >= 0 and
63
- i .getAnOperand ( ) = addr
64
- |
65
- i instanceof StoreInstruction and
66
- operation = "write"
67
- or
68
- i instanceof LoadInstruction and
69
- operation = "read"
83
+ bounded1 ( addr .getDef ( ) , sink .asInstruction ( ) , delta ) and
84
+ isInvalidPointerDerefSinkImpl ( delta , i , addr , operation )
85
+ )
86
+ }
87
+
88
+ pragma [ inline]
89
+ predicate isInvalidPointerDerefSink2 ( DataFlow:: Node sink , Instruction i , string operation ) {
90
+ exists ( AddressOperand addr , int delta |
91
+ bounded2 ( addr .getDef ( ) , sink .asInstruction ( ) , delta ) and
92
+ isInvalidPointerDerefSinkImpl ( delta , i , addr , operation )
70
93
)
71
94
}
72
95
@@ -90,7 +113,7 @@ module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
90
113
}
91
114
92
115
pragma [ inline]
93
- predicate isSink ( DataFlow:: Node sink ) { isInvalidPointerDerefSink ( sink , _, _) }
116
+ predicate isSink ( DataFlow:: Node sink ) { isInvalidPointerDerefSink1 ( sink , _, _) }
94
117
}
95
118
96
119
module PointerArithmeticToDerefFlow = DataFlow:: Global< PointerArithmeticToDerefConfig > ;
100
123
PointerArithmeticToDerefFlow:: PathNode sink , Instruction deref , string operation , int delta
101
124
where
102
125
PointerArithmeticToDerefFlow:: flowPath ( source , sink ) and
103
- isInvalidPointerDerefSink ( sink .getNode ( ) , deref , operation ) and
126
+ isInvalidPointerDerefSink2 ( sink .getNode ( ) , deref , operation ) and
104
127
isConstantSizeOverflowSource ( f , source .getNode ( ) .asInstruction ( ) , delta )
105
128
select source , source , sink ,
106
129
"This pointer arithmetic may have an off-by-" + ( delta + 1 ) +
0 commit comments