Skip to content

Commit a8b0d29

Browse files
committed
Ruby: More string comparison guards
Recognise if statements with conditionals made up or logical `and` or `or` clauses as barrier guards.
1 parent ad7b5ae commit a8b0d29

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ private predicate stringConstCompare(CfgNodes::AstCfgNode guard, CfgNode testedN
2525
)
2626
or
2727
stringConstCaseCompare(guard, testedNode, branch)
28+
or
29+
stringConstCompareOr(guard, testedNode, branch)
30+
or
31+
stringConstCompareAnd(guard, testedNode, branch)
32+
}
33+
34+
private predicate stringConstCompareOr(
35+
CfgNodes::ExprNodes::BinaryOperationCfgNode guard, CfgNode testedNode, boolean branch
36+
) {
37+
guard.getExpr() instanceof LogicalOrExpr and
38+
branch = true and
39+
exists(Ssa::Definition def |
40+
forall(CfgNode innerGuard | innerGuard = guard.getAnOperand() |
41+
stringConstCompare(innerGuard, def.getARead(), branch)
42+
) and
43+
testedNode = any(CfgNode node | stringConstCompare(guard.getAnOperand(), node, _))
44+
)
45+
}
46+
47+
private predicate stringConstCompareAnd(
48+
CfgNodes::ExprNodes::BinaryOperationCfgNode guard, CfgNode testedNode, boolean branch
49+
) {
50+
guard.getExpr() instanceof LogicalAndExpr and
51+
branch = true and
52+
stringConstCompare(guard.getAnOperand(), testedNode, branch)
2853
}
2954

3055
/**

ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.rb

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@
136136
end
137137

138138
case foo
139-
when "foo", "bar" # $ MISSING: guarded
140-
foo
141-
when "baz", "quux" # $ MISSING: guarded
142-
foo
139+
when "foo", "bar"
140+
foo # $ MISSING: guarded
141+
when "baz", "quux"
142+
foo # $ MISSING: guarded
143143
else
144144
foo
145145
end
@@ -189,7 +189,43 @@
189189
end
190190

191191
if foo == "foo" or foo == "bar"
192-
foo # $ MISSING: guarded
192+
foo # $ guarded
193+
end
194+
195+
if foo == "foo" or foo == "bar" or foo == "baz"
196+
foo # $ guarded
197+
end
198+
199+
if foo == "foo" or foo == "bar" or foo == x
200+
foo
201+
end
202+
203+
if foo == "foo" or bar == "bar" or foo == "baz"
204+
foo
205+
end
206+
207+
if foo == "foo" and x
208+
foo # $ guarded
209+
end
210+
211+
if x and foo == "foo"
212+
foo # $ guarded
213+
end
214+
215+
if x and y and foo == "foo"
216+
foo # $ guarded
217+
end
218+
219+
if foo == "foo" and foo == "bar" # $ guarded (second `foo` is guarded by the first comparison)
220+
foo # $ guarded
221+
end
222+
223+
if x and y
224+
foo
225+
end
226+
227+
if foo == "foo" and y
228+
bar
193229
end
194230

195231
case

0 commit comments

Comments
 (0)