Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 896dee5

Browse files
committed
C++: Fix dataflow pruning by evaluating successor before flowsToSink/flowsFromSource.
1 parent f2317ae commit 896dee5

1 file changed

Lines changed: 63 additions & 52 deletions

File tree

cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ predicate flowIntoParameter(
3333
not f.isVirtual() and
3434
call.getPositionalArgument(n) = instr and
3535
f = call.getStaticCallTarget() and
36-
init.getEnclosingFunction() = f and
36+
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
3737
init.getParameter().getIndex() = unbind(n)
3838
}
3939

@@ -62,7 +62,7 @@ predicate getThisArgumentInitParam(
6262
) {
6363
not f.isVirtual() and
6464
call.getStaticCallTarget() = f and
65-
init.getEnclosingFunction() = f and
65+
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
6666
call.getThisArgument() = instr and
6767
init.getIRVariable() instanceof IRThisVariable
6868
}
@@ -94,13 +94,19 @@ predicate isSource(InitializeParameterInstruction init, string msg, Class c) {
9494
init.getEnclosingFunction().getDeclaringType() = c
9595
}
9696

97-
/** Holds if `instr` flows to a sink. */
98-
predicate flowsToSink(Instruction instr) {
99-
isSink(instr, _, _)
100-
or
101-
exists(Instruction mid |
102-
successor(instr, mid) and
103-
flowsToSink(mid)
97+
/**
98+
* Holds if `instr` flows to a sink (which is a use of the value of `instr` as a `this` pointer
99+
* of type `sinkClass`).
100+
*/
101+
predicate flowsToSink(Instruction instr, Instruction sink, Class sinkClass) {
102+
flowsFromSource(instr) and
103+
(
104+
isSink(instr, _, sinkClass) and instr = sink
105+
or
106+
exists(Instruction mid |
107+
successor(instr, mid) and
108+
flowsToSink(mid, sink, sinkClass)
109+
)
104110
)
105111
}
106112

@@ -114,59 +120,67 @@ predicate flowsFromSource(Instruction instr) {
114120
)
115121
}
116122

123+
/** Holds if `f` is the enclosing non-virtual function of `init`. */
124+
predicate getEnclosingNonVirtualFunctionInitializeParameter(
125+
InitializeParameterInstruction init, Function f
126+
) {
127+
not f.isVirtual() and
128+
init.getEnclosingFunction() = f
129+
}
130+
131+
/** Holds if `f` is the enclosing non-virtual function of `init`. */
132+
predicate getEnclosingNonVirtualFunctionInitializeIndirection(
133+
InitializeIndirectionInstruction init, Function f
134+
) {
135+
not f.isVirtual() and
136+
init.getEnclosingFunction() = f
137+
}
138+
117139
/**
118140
* Holds if `instr` is an argument (or argument indirection) to a call, and
119141
* `succ` is the corresponding initialization instruction in the call target.
120142
*/
121143
predicate flowThroughCallable(Instruction instr, Instruction succ) {
122-
flowsToSink(succ) and
123-
(
124-
// Flow from an argument to a parameter
125-
exists(CallInstruction call, InitializeParameterInstruction init | init = succ |
126-
getPositionalArgumentInitParam(call, instr, init, call.getStaticCallTarget())
127-
or
128-
getThisArgumentInitParam(call, instr, init, call.getStaticCallTarget())
129-
)
144+
// Flow from an argument to a parameter
145+
exists(CallInstruction call, InitializeParameterInstruction init | init = succ |
146+
getPositionalArgumentInitParam(call, instr, init, call.getStaticCallTarget())
130147
or
131-
// Flow from argument indirection to parameter indirection
132-
exists(
133-
CallInstruction call, ReadSideEffectInstruction read, InitializeIndirectionInstruction init
134-
|
135-
init = succ and
136-
read.getPrimaryInstruction() = call and
137-
init.getEnclosingFunction() = call.getStaticCallTarget()
138-
|
139-
exists(int n |
140-
read.getSideEffectOperand().getAnyDef() = instr and
141-
read.getIndex() = n and
142-
init.getParameter().getIndex() = unbind(n)
143-
)
144-
or
145-
call.getThisArgument() = instr and
146-
init.getIRVariable() instanceof IRThisVariable
148+
getThisArgumentInitParam(call, instr, init, call.getStaticCallTarget())
149+
)
150+
or
151+
// Flow from argument indirection to parameter indirection
152+
exists(
153+
CallInstruction call, ReadSideEffectInstruction read, InitializeIndirectionInstruction init
154+
|
155+
init = succ and
156+
read.getPrimaryInstruction() = call and
157+
getEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget())
158+
|
159+
exists(int n |
160+
read.getSideEffectOperand().getAnyDef() = instr and
161+
read.getIndex() = n and
162+
init.getParameter().getIndex() = unbind(n)
147163
)
164+
or
165+
call.getThisArgument() = instr and
166+
init.getIRVariable() instanceof IRThisVariable
148167
)
149168
}
150169

151170
/** Holds if `instr` flows to `succ`. */
152171
predicate successor(Instruction instr, Instruction succ) {
153-
flowsToSink(succ) and
172+
succ.getBlock().postDominates(instr.getBlock()) and
154173
(
155-
irBbPostDominates(succ.getBlock(), instr.getBlock()) and
156-
(
157-
succ.(CopyInstruction).getSourceValue() = instr or
158-
succ.(CheckedConvertOrNullInstruction).getUnary() = instr or
159-
succ.(ChiInstruction).getTotal() = instr or
160-
succ.(ConvertInstruction).getUnary() = instr or
161-
succ.(InheritanceConversionInstruction).getUnary() = instr
162-
)
163-
or
164-
flowThroughCallable(instr, succ)
174+
succ.(CopyInstruction).getSourceValue() = instr or
175+
succ.(CheckedConvertOrNullInstruction).getUnary() = instr or
176+
succ.(ChiInstruction).getTotal() = instr or
177+
succ.(ConvertInstruction).getUnary() = instr or
178+
succ.(InheritanceConversionInstruction).getUnary() = instr
165179
)
180+
or
181+
flowThroughCallable(instr, succ)
166182
}
167183

168-
predicate successorTC(Instruction i1, Instruction i2) = fastTC(successor/2)(i1, i2)
169-
170184
/**
171185
* Holds if:
172186
* - `source` is an initialization of a `this` pointer of type `sourceClass`, and
@@ -179,17 +193,14 @@ predicate flows(
179193
Class sinkClass
180194
) {
181195
isSource(source, msg, sourceClass) and
182-
successorTC(source, sink) and
196+
flowsToSink(source, sink, sinkClass) and
183197
isSink(sink, call, sinkClass)
184198
}
185199

186-
query predicate edges(Instruction a, Instruction b) {
187-
successor(a, b) and flowsFromSource(a) and flowsFromSource(b)
188-
}
200+
query predicate edges(Instruction a, Instruction b) { successor(a, b) and flowsToSink(b, _, _) }
189201

190202
query predicate nodes(Instruction n, string key, string val) {
191-
flowsFromSource(n) and
192-
flowsToSink(n) and
203+
flowsToSink(n, _, _) and
193204
key = "semmle.label" and
194205
val = n.toString()
195206
}

0 commit comments

Comments
 (0)