Ruby: More string comparison guards

Recognise if statements with conditionals made up or logical `and` or
`or` clauses as barrier guards.
This commit is contained in:
Harry Maclean
2022-11-10 16:38:09 +13:00
parent ad7b5ae7ed
commit a8b0d298ff
2 changed files with 66 additions and 5 deletions

View File

@@ -25,6 +25,31 @@ private predicate stringConstCompare(CfgNodes::AstCfgNode guard, CfgNode testedN
)
or
stringConstCaseCompare(guard, testedNode, branch)
or
stringConstCompareOr(guard, testedNode, branch)
or
stringConstCompareAnd(guard, testedNode, branch)
}
private predicate stringConstCompareOr(
CfgNodes::ExprNodes::BinaryOperationCfgNode guard, CfgNode testedNode, boolean branch
) {
guard.getExpr() instanceof LogicalOrExpr and
branch = true and
exists(Ssa::Definition def |
forall(CfgNode innerGuard | innerGuard = guard.getAnOperand() |
stringConstCompare(innerGuard, def.getARead(), branch)
) and
testedNode = any(CfgNode node | stringConstCompare(guard.getAnOperand(), node, _))
)
}
private predicate stringConstCompareAnd(
CfgNodes::ExprNodes::BinaryOperationCfgNode guard, CfgNode testedNode, boolean branch
) {
guard.getExpr() instanceof LogicalAndExpr and
branch = true and
stringConstCompare(guard.getAnOperand(), testedNode, branch)
}
/**

View File

@@ -136,10 +136,10 @@ when "bar"
end
case foo
when "foo", "bar" # $ MISSING: guarded
foo
when "baz", "quux" # $ MISSING: guarded
foo
when "foo", "bar"
foo # $ MISSING: guarded
when "baz", "quux"
foo # $ MISSING: guarded
else
foo
end
@@ -189,7 +189,43 @@ when *FOO_AND_X # not a guard - includes non-constant element `x`
end
if foo == "foo" or foo == "bar"
foo # $ MISSING: guarded
foo # $ guarded
end
if foo == "foo" or foo == "bar" or foo == "baz"
foo # $ guarded
end
if foo == "foo" or foo == "bar" or foo == x
foo
end
if foo == "foo" or bar == "bar" or foo == "baz"
foo
end
if foo == "foo" and x
foo # $ guarded
end
if x and foo == "foo"
foo # $ guarded
end
if x and y and foo == "foo"
foo # $ guarded
end
if foo == "foo" and foo == "bar" # $ guarded (second `foo` is guarded by the first comparison)
foo # $ guarded
end
if x and y
foo
end
if foo == "foo" and y
bar
end
case