Skip to content

Commit 0cae6de

Browse files
authored
Merge pull request #10513 from erik-krogh/more-alert-style
QL: improve the `ql/alert-message-style-violation` query.
2 parents 99e8cb7 + 1bdb6b4 commit 0cae6de

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

ql/ql/src/codeql_ql/ast/Ast.qll

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ class QueryDoc extends QLDoc {
186186
override string getAPrimaryQlClass() { result = "QueryDoc" }
187187

188188
/** Gets the @kind for the query */
189-
string getQueryKind() { result = this.getContents().regexpCapture("(?s).*@kind (\\w+)\\s.*", 1) }
189+
string getQueryKind() {
190+
result = this.getContents().regexpCapture("(?s).*@kind ([\\w-]+)\\s.*", 1)
191+
}
190192

191193
/** Gets the id part (without language) of the @id */
192194
string getQueryId() {
@@ -242,6 +244,12 @@ class Select extends TSelect, AstNode {
242244
*/
243245
Expr getExpr(int i) { toQL(result) = sel.getChild(_).(QL::AsExprs).getChild(i) }
244246

247+
Expr getMessage() {
248+
if this.getQueryDoc().getQueryKind() = "path-problem"
249+
then result = this.getExpr(3)
250+
else result = this.getExpr(1)
251+
}
252+
245253
// TODO: This gets the `i`th order-by, but some expressions might not have an order-by.
246254
Expr getOrderBy(int i) { toQL(result) = sel.getChild(_).(QL::OrderBys).getChild(i).getChild(0) }
247255

@@ -1403,6 +1411,14 @@ class ComparisonFormula extends TComparisonFormula, Formula {
14031411
or
14041412
pred = directMember("getRightOperand") and result = this.getRightOperand()
14051413
}
1414+
1415+
/** Holds if this comparison has the operands `a` and `b` (in any order). */
1416+
pragma[noinline]
1417+
predicate hasOperands(Expr a, Expr b) {
1418+
this.getLeftOperand() = a and this.getRightOperand() = b
1419+
or
1420+
this.getLeftOperand() = b and this.getRightOperand() = a
1421+
}
14061422
}
14071423

14081424
/** A quantifier formula, such as `exists` or `forall`. */

ql/ql/src/queries/style/AlertMessage.ql

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@
1010

1111
import ql
1212

13+
AstNode getASubExpression(Select sel) {
14+
result = sel.getExpr(_)
15+
or
16+
result = getASubExpression(sel).getAChild()
17+
}
18+
1319
/** Gets the `index`th part of the select statement. */
1420
private AstNode getSelectPart(Select sel, int index) {
1521
result =
1622
rank[index](AstNode n, Location loc |
1723
(
18-
n.getParent*() = sel.getExpr(_) and loc = n.getLocation()
24+
n = getASubExpression(sel) and loc = n.getLocation()
1925
or
2026
// the strings are behind a predicate call.
21-
exists(Call c, Predicate target |
22-
c.getParent*() = sel.getExpr(_) and loc = c.getLocation()
23-
|
27+
exists(Call c, Predicate target | c = getASubExpression(sel) and loc = c.getLocation() |
2428
c.getTarget() = target and
2529
(
2630
target.getBody().(ComparisonFormula).getAnOperand() = n
@@ -30,6 +34,14 @@ private AstNode getSelectPart(Select sel, int index) {
3034
)
3135
)
3236
)
37+
or
38+
// the string is a variable that is assigned in the `where` clause.
39+
exists(VarAccess v, ComparisonFormula comp, String str |
40+
v = getASubExpression(sel) and
41+
loc = v.getLocation() and
42+
comp.hasOperands(v.getDeclaration().getAnAccess(), str) and
43+
n = str
44+
)
3345
)
3446
|
3547
n
@@ -52,7 +64,7 @@ private AstNode getSelectPart(Select sel, int index) {
5264
String shouldHaveFullStop(Select sel) {
5365
result =
5466
max(AstNode str, int i |
55-
str.getParent+() = sel.getExpr(1) and str = getSelectPart(sel, i)
67+
str.getParent*() = sel.getMessage() and str = getSelectPart(sel, i)
5668
|
5769
str order by i
5870
) and
@@ -73,7 +85,7 @@ String shouldHaveFullStop(Select sel) {
7385
String shouldStartCapital(Select sel) {
7486
result =
7587
min(AstNode str, int i |
76-
str.getParent+() = sel.getExpr(1) and str = getSelectPart(sel, i)
88+
str.getParent*() = sel.getMessage() and str = getSelectPart(sel, i)
7789
|
7890
str order by i
7991
) and
@@ -164,6 +176,14 @@ String wrongFlowsPhrase(Select sel, string kind) {
164176
)
165177
}
166178

179+
/**
180+
* Gets a string element that contains double whitespace.
181+
*/
182+
String doubleWhitespace(Select sel) {
183+
result = getSelectPart(sel, _) and
184+
result.getValue().regexpMatch(".*\\s\\s.*")
185+
}
186+
167187
from AstNode node, string msg
168188
where
169189
not node.getLocation().getFile().getAbsolutePath().matches("%/test/%") and
@@ -194,5 +214,8 @@ where
194214
or
195215
node = wrongFlowsPhrase(_, "taint") and
196216
msg = "Use \"depends on\" instead of \"flows to\" in taint tracking queries."
217+
or
218+
node = doubleWhitespace(_) and
219+
msg = "Avoid using double whitespace in alert messages."
197220
)
198221
select node, msg

0 commit comments

Comments
 (0)