@@ -7,12 +7,16 @@ private import codeql.ruby.controlflow.CfgNodes
77private import codeql.ruby.dataflow.SSA
88private import codeql.ruby.ast.internal.Constant
99private import codeql.ruby.InclusionTests
10+ private import codeql.ruby.ast.internal.Literal
1011
1112private predicate stringConstCompare ( CfgNodes:: AstCfgNode guard , CfgNode testedNode , boolean branch ) {
1213 exists ( CfgNodes:: ExprNodes:: ComparisonOperationCfgNode c |
1314 c = guard and
1415 exists ( CfgNodes:: ExprNodes:: StringLiteralCfgNode strLitNode |
15- c .getExpr ( ) instanceof EqExpr and branch = true
16+ // Only consider strings without any interpolations
17+ not exists ( StringInterpolationComponent comp | comp = strLitNode .getExpr ( ) .getComponent ( _) ) and
18+ c .getExpr ( ) instanceof EqExpr and
19+ branch = true
1620 or
1721 c .getExpr ( ) instanceof CaseEqExpr and branch = true
1822 or
@@ -26,24 +30,43 @@ private predicate stringConstCompare(CfgNodes::AstCfgNode guard, CfgNode testedN
2630 or
2731 stringConstCaseCompare ( guard , testedNode , branch )
2832 or
29- stringConstCompareOr ( guard , testedNode , branch )
33+ exists ( Ssa:: Definition def , CfgNodes:: ExprNodes:: BinaryOperationCfgNode g |
34+ g = guard and
35+ stringConstCompareOr ( guard , def , branch ) and
36+ stringConstCompare ( g .getLeftOperand ( ) , testedNode , _)
37+ )
3038 or
3139 stringConstCompareAnd ( guard , testedNode , branch )
3240}
3341
42+ /**
43+ * Holds if `guard` is an `or` expression whose operands are string comparison guards that test the same SSA variable.
44+ * `testedNode` is an arbitrary node that is tested by one of the guards.
45+ * For example:
46+ *
47+ * ```rb
48+ * x == "foo" or x == "bar"
49+ * ```
50+ */
3451private predicate stringConstCompareOr (
35- CfgNodes:: ExprNodes:: BinaryOperationCfgNode guard , CfgNode testedNode , boolean branch
52+ CfgNodes:: ExprNodes:: BinaryOperationCfgNode guard , Ssa :: Definition def , boolean branch
3653) {
3754 guard .getExpr ( ) instanceof LogicalOrExpr and
3855 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 , _) )
56+ forall ( CfgNode innerGuard | innerGuard = guard .getAnOperand ( ) |
57+ stringConstCompare ( innerGuard , def .getARead ( ) , branch )
4458 )
4559}
4660
61+ /**
62+ * Holds if guard is an `and` expression containing a string comparison guard in either operand.
63+ * For example:
64+ *
65+ * ```rb
66+ * x == "foo" and other_condition()
67+ * other_condition() and x == "foo"
68+ * ```
69+ */
4770private predicate stringConstCompareAnd (
4871 CfgNodes:: ExprNodes:: BinaryOperationCfgNode guard , CfgNode testedNode , boolean branch
4972) {
0 commit comments