Skip to content

Commit 172684c

Browse files
authored
QL: Merge pull request #137 from github/erik-krogh/even-more-consistency
even more consistency
2 parents 44ffc7e + 70f6493 commit 172684c

File tree

26 files changed

+337
-130
lines changed

26 files changed

+337
-130
lines changed

ql/src/codeql_ql/performance/InefficientStringComparisonQuery.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ class RegexpMatchPredicate extends BuiltinPredicate {
4545
predicate canUseMatchInsteadOfRegexpMatch(Call c, string matchesStr) {
4646
c.getTarget() instanceof RegexpMatchPredicate and
4747
exists(string raw | raw = c.getArgument(0).(String).getValue() |
48-
matchesStr = "%" + raw.regexpCapture("^\\.\\*(\\w+)$", _)
48+
matchesStr = "%" + raw.regexpCapture("^\\.\\*([a-zA-Z\\d\\s-]+)$", _)
4949
or
50-
matchesStr = raw.regexpCapture("^(\\w+)\\.\\*$", _) + "%"
50+
matchesStr = raw.regexpCapture("^([a-zA-Z\\d\\s-]+)\\.\\*$", _) + "%"
5151
or
52-
matchesStr = "%" + raw.regexpCapture("^\\.\\*(\\w+)\\.\\*$", _) + "%"
52+
matchesStr = "%" + raw.regexpCapture("^\\.\\*([a-zA-Z\\d\\s-]+)\\.\\*$", _) + "%"
5353
)
5454
}

ql/src/queries/diagnostics/EmptyConsistencies.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ where
3333
or
3434
AstConsistency::nonTotalGetParent(node) and msg = "AstConsistency::nonTotalGetParent"
3535
or
36-
//or // has 1 result, but the CodeQL compiler also can't figure out that one. I suppoed the file is never imported.
37-
//TypeConsistency::noResolve(node) and msg = "TypeConsistency::noResolve"
38-
//or // has 1 result, but the CodeQL compiler also can't figure out that one. Same file as above.
39-
//ModConsistency::noResolve(node) and msg = "ModConsistency::noResolve"
36+
TypeConsistency::noResolve(node) and msg = "TypeConsistency::noResolve"
37+
or
38+
ModConsistency::noResolve(node) and msg = "ModConsistency::noResolve"
39+
or
4040
ModConsistency::noResolveModuleExpr(node) and msg = "ModConsistency::noResolveModuleExpr"
4141
or
4242
VarConsistency::noFieldDef(node) and msg = "VarConsistency::noFieldDef"

repo-tests/codeql.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6c2713dd8bf76ae1207e3123900a04d6f89b5162
1+
1f3f7e9ccc631177f671f3d465faec3477cbe1c5

repo-tests/codeql/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class SqliteFunctionCall extends FunctionCall {
2929
}
3030

3131
predicate sqlite_encryption_used() {
32-
any(StringLiteral l).getValue().toLowerCase().regexpMatch("pragma key.*") or
32+
any(StringLiteral l).getValue().toLowerCase().matches("pragma key%") or
3333
any(StringLiteral l).getValue().toLowerCase().matches("%attach%database%key%") or
3434
any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%")
3535
}

repo-tests/codeql/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,13 @@ module ControlFlow {
268268

269269
/** A node for a callable exit point, annotated with the type of exit. */
270270
class AnnotatedExitNode extends Node, TAnnotatedExitNode {
271-
private Callable c;
271+
private CfgScope scope;
272272
private boolean normal;
273273

274-
AnnotatedExitNode() { this = TAnnotatedExitNode(c, normal) }
274+
AnnotatedExitNode() { this = TAnnotatedExitNode(scope, normal) }
275275

276276
/** Gets the callable that this exit applies to. */
277-
Callable getCallable() { result = c }
277+
CfgScope getCallable() { result = scope }
278278

279279
/** Holds if this node represents a normal exit. */
280280
predicate isNormal() { normal = true }
@@ -285,31 +285,35 @@ module ControlFlow {
285285

286286
override Callable getEnclosingCallable() { result = this.getCallable() }
287287

288-
override Location getLocation() { result = this.getCallable().getLocation() }
288+
override Location getLocation() { result = scope.getLocation() }
289289

290290
override string toString() {
291291
exists(string s |
292292
normal = true and s = "normal"
293293
or
294294
normal = false and s = "abnormal"
295295
|
296-
result = "exit " + this.getCallable() + " (" + s + ")"
296+
result = "exit " + scope + " (" + s + ")"
297297
)
298298
}
299299
}
300300

301301
/** A node for a callable exit point. */
302302
class ExitNode extends Node, TExitNode {
303+
private CfgScope scope;
304+
305+
ExitNode() { this = TExitNode(scope) }
306+
303307
/** Gets the callable that this exit applies to. */
304-
Callable getCallable() { this = TExitNode(result) }
308+
Callable getCallable() { result = scope }
305309

306310
override BasicBlocks::ExitBlock getBasicBlock() { result = Node.super.getBasicBlock() }
307311

308312
override Callable getEnclosingCallable() { result = this.getCallable() }
309313

310-
override Location getLocation() { result = this.getCallable().getLocation() }
314+
override Location getLocation() { result = scope.getLocation() }
311315

312-
override string toString() { result = "exit " + this.getCallable().toString() }
316+
override string toString() { result = "exit " + scope }
313317
}
314318

315319
/**

repo-tests/codeql/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ module ControlFlowTree {
9797
predicate idOf(Range_ x, int y) = equivalenceRelation(id/2)(x, y)
9898
}
9999

100+
/**
101+
* The `expr_parent_top_level_adjusted()` relation restricted to exclude relations
102+
* between properties and their getters' expression bodies in properties such as
103+
* `int P => 0`.
104+
*
105+
* This is in order to only associate the expression body with one CFG scope, namely
106+
* the getter (and not the declaration itself).
107+
*/
108+
private predicate expr_parent_top_level_adjusted2(
109+
Expr child, int i, @top_level_exprorstmt_parent parent
110+
) {
111+
expr_parent_top_level_adjusted(child, i, parent) and
112+
not exists(Getter g |
113+
g.getDeclaration() = parent and
114+
i = 0
115+
)
116+
}
117+
100118
/** Holds if `first` is first executed when entering `scope`. */
101119
predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
102120
scope =
@@ -109,17 +127,23 @@ predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
109127
else first(c.getBody(), first)
110128
)
111129
or
112-
expr_parent_top_level_adjusted(any(Expr e | first(e, first)), _, scope) and
130+
expr_parent_top_level_adjusted2(any(Expr e | first(e, first)), _, scope) and
113131
not scope instanceof Callable
114132
}
115133

116134
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
117-
predicate scopeLast(Callable scope, ControlFlowElement last, Completion c) {
118-
last(scope.getBody(), last, c) and
119-
not c instanceof GotoCompletion
135+
predicate scopeLast(CfgScope scope, ControlFlowElement last, Completion c) {
136+
scope =
137+
any(Callable callable |
138+
last(callable.getBody(), last, c) and
139+
not c instanceof GotoCompletion
140+
or
141+
last(InitializerSplitting::lastConstructorInitializer(scope, _), last, c) and
142+
not callable.hasBody()
143+
)
120144
or
121-
last(InitializerSplitting::lastConstructorInitializer(scope, _), last, c) and
122-
not scope.hasBody()
145+
expr_parent_top_level_adjusted2(any(Expr e | last(e, last, c)), _, scope) and
146+
not scope instanceof Callable
123147
}
124148

125149
private class ConstructorTree extends ControlFlowTree, Constructor {

repo-tests/codeql/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ module Public {
8585
/** Holds if this stack contains summary component `c`. */
8686
predicate contains(SummaryComponent c) { c = this.drop(_).head() }
8787

88+
/** Gets the bottom element of this stack. */
89+
SummaryComponent bottom() { result = this.drop(this.length() - 1).head() }
90+
8891
/** Gets a textual representation of this stack. */
8992
string toString() {
9093
exists(SummaryComponent head, SummaryComponentStack tail |
@@ -197,6 +200,8 @@ module Private {
197200
or
198201
tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and
199202
head = thisParam()
203+
or
204+
derivedFluentFlowPush(_, _, _, head, tail, _)
200205
}
201206

202207
pragma[nomagic]
@@ -210,7 +215,7 @@ module Private {
210215
c.propagatesFlow(output, input, preservesValue) and
211216
preservesValue = true and
212217
isCallbackParameter(input) and
213-
isContentOfArgument(output)
218+
isContentOfArgument(output, _)
214219
or
215220
// flow from the receiver of a callback into the instance-parameter
216221
exists(SummaryComponentStack s, SummaryComponentStack callbackRef |
@@ -222,16 +227,81 @@ module Private {
222227
output = TConsSummaryComponentStack(thisParam(), input) and
223228
preservesValue = true
224229
)
230+
or
231+
exists(SummaryComponentStack arg, SummaryComponentStack return |
232+
derivedFluentFlow(c, input, arg, return, preservesValue)
233+
|
234+
arg.length() = 1 and
235+
output = return
236+
or
237+
exists(SummaryComponent head, SummaryComponentStack tail |
238+
derivedFluentFlowPush(c, input, arg, head, tail, 0) and
239+
output = SummaryComponentStack::push(head, tail)
240+
)
241+
)
242+
or
243+
// Chain together summaries where values get passed into callbacks along the way
244+
exists(SummaryComponentStack mid, boolean preservesValue1, boolean preservesValue2 |
245+
c.propagatesFlow(input, mid, preservesValue1) and
246+
c.propagatesFlow(mid, output, preservesValue2) and
247+
mid.drop(mid.length() - 2) =
248+
SummaryComponentStack::push(TParameterSummaryComponent(_),
249+
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
250+
preservesValue = preservesValue1.booleanAnd(preservesValue2)
251+
)
252+
}
253+
254+
/**
255+
* Holds if `c` has a flow summary from `input` to `arg`, where `arg`
256+
* writes to (contents of) the `i`th argument, and `c` has a
257+
* value-preserving flow summary from the `i`th argument to a return value
258+
* (`return`).
259+
*
260+
* In such a case, we derive flow from `input` to (contents of) the return
261+
* value.
262+
*
263+
* As an example, this simplifies modeling of fluent methods:
264+
* for `StringBuilder.append(x)` with a specified value flow from qualifier to
265+
* return value and taint flow from argument 0 to the qualifier, then this
266+
* allows us to infer taint flow from argument 0 to the return value.
267+
*/
268+
pragma[nomagic]
269+
private predicate derivedFluentFlow(
270+
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
271+
SummaryComponentStack return, boolean preservesValue
272+
) {
273+
exists(int i |
274+
summary(c, input, arg, preservesValue) and
275+
isContentOfArgument(arg, i) and
276+
summary(c, SummaryComponentStack::singleton(TArgumentSummaryComponent(i)), return, true) and
277+
return.bottom() = TReturnSummaryComponent(_)
278+
)
279+
}
280+
281+
pragma[nomagic]
282+
private predicate derivedFluentFlowPush(
283+
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
284+
SummaryComponent head, SummaryComponentStack tail, int i
285+
) {
286+
derivedFluentFlow(c, input, arg, tail, _) and
287+
head = arg.drop(i).head() and
288+
i = arg.length() - 2
289+
or
290+
exists(SummaryComponent head0, SummaryComponentStack tail0 |
291+
derivedFluentFlowPush(c, input, arg, head0, tail0, i + 1) and
292+
head = arg.drop(i).head() and
293+
tail = SummaryComponentStack::push(head0, tail0)
294+
)
225295
}
226296

227297
private predicate isCallbackParameter(SummaryComponentStack s) {
228298
s.head() = TParameterSummaryComponent(_) and exists(s.tail())
229299
}
230300

231-
private predicate isContentOfArgument(SummaryComponentStack s) {
232-
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail())
301+
private predicate isContentOfArgument(SummaryComponentStack s, int i) {
302+
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail(), i)
233303
or
234-
s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(_))
304+
s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(i))
235305
}
236306

237307
private predicate outputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -508,9 +578,14 @@ module Private {
508578
* node, and back out to `p`.
509579
*/
510580
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
511-
exists(SummarizedCallable c, int i |
512-
c.clearsContent(i, _) and
513-
p.isParameterOf(c, i)
581+
exists(SummarizedCallable c, int i | p.isParameterOf(c, i) |
582+
c.clearsContent(i, _)
583+
or
584+
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
585+
summary(c, inputContents, outputContents, _) and
586+
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i)) and
587+
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i))
588+
)
514589
)
515590
}
516591

@@ -534,22 +609,6 @@ module Private {
534609
preservesValue = false and not summary(c, inputContents, outputContents, true)
535610
)
536611
or
537-
// If flow through a method updates a parameter from some input A, and that
538-
// parameter also is returned through B, then we'd like a combined flow from A
539-
// to B as well. As an example, this simplifies modeling of fluent methods:
540-
// for `StringBuilder.append(x)` with a specified value flow from qualifier to
541-
// return value and taint flow from argument 0 to the qualifier, then this
542-
// allows us to infer taint flow from argument 0 to the return value.
543-
succ instanceof ParamNode and
544-
summaryPostUpdateNode(pred, succ) and
545-
preservesValue = true
546-
or
547-
// Similarly we would like to chain together summaries where values get passed
548-
// into callbacks along the way.
549-
pred instanceof ArgNode and
550-
summaryPostUpdateNode(succ, pred) and
551-
preservesValue = true
552-
or
553612
exists(SummarizedCallable c, int i |
554613
pred.(ParamNode).isParameterOf(c, i) and
555614
succ = summaryNode(c, TSummaryNodeClearsContentState(i, _)) and

repo-tests/codeql/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -174,32 +174,34 @@ module EntityFramework {
174174
}
175175
}
176176

177-
private class RawSqlStringSummarizedCallable extends EFSummarizedCallable {
178-
private SummaryComponentStack input_;
179-
private SummaryComponentStack output_;
180-
private boolean preservesValue_;
181-
182-
RawSqlStringSummarizedCallable() {
177+
private class RawSqlStringConstructorSummarizedCallable extends EFSummarizedCallable {
178+
RawSqlStringConstructorSummarizedCallable() {
183179
exists(RawSqlStringStruct s |
184180
this = s.getAConstructor() and
185-
input_ = SummaryComponentStack::argument(0) and
186-
this.getNumberOfParameters() > 0 and
187-
output_ = SummaryComponentStack::return() and
188-
preservesValue_ = false
189-
or
190-
this = s.getAConversionTo() and
191-
input_ = SummaryComponentStack::argument(0) and
192-
output_ = SummaryComponentStack::return() and
193-
preservesValue_ = false
181+
this.getNumberOfParameters() > 0
194182
)
195183
}
196184

197185
override predicate propagatesFlow(
198186
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
199187
) {
200-
input = input_ and
201-
output = output_ and
202-
preservesValue = preservesValue_
188+
input = SummaryComponentStack::argument(0) and
189+
output = SummaryComponentStack::return() and
190+
preservesValue = false
191+
}
192+
}
193+
194+
private class RawSqlStringConversionSummarizedCallable extends EFSummarizedCallable {
195+
RawSqlStringConversionSummarizedCallable() {
196+
exists(RawSqlStringStruct s | this = s.getAConversionTo())
197+
}
198+
199+
override predicate propagatesFlow(
200+
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
201+
) {
202+
input = SummaryComponentStack::argument(0) and
203+
output = SummaryComponentStack::return() and
204+
preservesValue = false
203205
}
204206
}
205207

repo-tests/codeql/csharp/ql/src/Linq/BadMultipleIteration.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313

1414
import csharp
15-
import Helpers
15+
import Linq.Helpers
1616

1717
/** The enumerable sequence is likely not to be repeatable. */
1818
predicate likelyNonRepeatableSequence(IEnumerableSequence seq) {

0 commit comments

Comments
 (0)