Skip to content

Commit ae1f5bb

Browse files
authored
Merge pull request github#9334 from hvitved/ruby/dataflow/hash-splat-literal
2 parents da90440 + b3ce2d4 commit ae1f5bb

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ SummaryComponent interpretComponentSpecific(AccessPathToken c) {
9494
ppos.isAny()
9595
or
9696
ppos.isPositionalLowerBound(AccessPath::parseLowerBound(arg))
97+
or
98+
arg = "hash-splat" and
99+
ppos.isHashSplat()
97100
)
98101
or
99102
result = interpretElementArg(c.getAnArgument("Element"))

ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,22 @@ module Hash {
6565
}
6666
}
6767

68+
private class HashLiteralHashSplatSummary extends SummarizedCallable {
69+
HashLiteralHashSplatSummary() { this = "Hash.[**]" }
70+
71+
final override MethodCall getACall() {
72+
result = API::getTopLevelMember("Hash").getAMethodCall("[]").getExprNode().getExpr() and
73+
result.getAnArgument() instanceof HashSplatExpr
74+
}
75+
76+
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
77+
// { **hash }
78+
input = "Argument[hash-splat].WithElement[any]" and
79+
output = "ReturnValue" and
80+
preservesValue = true
81+
}
82+
}
83+
6884
/**
6985
* `Hash[]` called on an existing hash, e.g.
7086
*

ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,24 @@ edges
508508
| hash_flow.rb:721:9:721:12 | hash [element :c] : | hash_flow.rb:721:9:721:31 | call to fetch_values [element] : |
509509
| hash_flow.rb:721:9:721:31 | call to fetch_values [element] : | hash_flow.rb:722:10:722:10 | b [element] : |
510510
| hash_flow.rb:722:10:722:10 | b [element] : | hash_flow.rb:722:10:722:13 | ...[...] |
511+
| hash_flow.rb:729:15:729:25 | call to taint : | hash_flow.rb:738:16:738:20 | hash1 [element :a] : |
512+
| hash_flow.rb:731:15:731:25 | call to taint : | hash_flow.rb:738:16:738:20 | hash1 [element :c] : |
513+
| hash_flow.rb:734:15:734:25 | call to taint : | hash_flow.rb:738:44:738:48 | hash2 [element :d] : |
514+
| hash_flow.rb:736:15:736:25 | call to taint : | hash_flow.rb:738:44:738:48 | hash2 [element :f] : |
515+
| hash_flow.rb:738:14:738:20 | ** ... [element :a] : | hash_flow.rb:739:10:739:13 | hash [element :a] : |
516+
| hash_flow.rb:738:14:738:20 | ** ... [element :c] : | hash_flow.rb:741:10:741:13 | hash [element :c] : |
517+
| hash_flow.rb:738:16:738:20 | hash1 [element :a] : | hash_flow.rb:738:14:738:20 | ** ... [element :a] : |
518+
| hash_flow.rb:738:16:738:20 | hash1 [element :c] : | hash_flow.rb:738:14:738:20 | ** ... [element :c] : |
519+
| hash_flow.rb:738:29:738:39 | call to taint : | hash_flow.rb:745:10:745:13 | hash [element :g] : |
520+
| hash_flow.rb:738:42:738:48 | ** ... [element :d] : | hash_flow.rb:742:10:742:13 | hash [element :d] : |
521+
| hash_flow.rb:738:42:738:48 | ** ... [element :f] : | hash_flow.rb:744:10:744:13 | hash [element :f] : |
522+
| hash_flow.rb:738:44:738:48 | hash2 [element :d] : | hash_flow.rb:738:42:738:48 | ** ... [element :d] : |
523+
| hash_flow.rb:738:44:738:48 | hash2 [element :f] : | hash_flow.rb:738:42:738:48 | ** ... [element :f] : |
524+
| hash_flow.rb:739:10:739:13 | hash [element :a] : | hash_flow.rb:739:10:739:17 | ...[...] |
525+
| hash_flow.rb:741:10:741:13 | hash [element :c] : | hash_flow.rb:741:10:741:17 | ...[...] |
526+
| hash_flow.rb:742:10:742:13 | hash [element :d] : | hash_flow.rb:742:10:742:17 | ...[...] |
527+
| hash_flow.rb:744:10:744:13 | hash [element :f] : | hash_flow.rb:744:10:744:17 | ...[...] |
528+
| hash_flow.rb:745:10:745:13 | hash [element :g] : | hash_flow.rb:745:10:745:17 | ...[...] |
511529
nodes
512530
| hash_flow.rb:11:15:11:24 | call to taint : | semmle.label | call to taint : |
513531
| hash_flow.rb:13:12:13:21 | call to taint : | semmle.label | call to taint : |
@@ -1062,6 +1080,29 @@ nodes
10621080
| hash_flow.rb:721:9:721:31 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : |
10631081
| hash_flow.rb:722:10:722:10 | b [element] : | semmle.label | b [element] : |
10641082
| hash_flow.rb:722:10:722:13 | ...[...] | semmle.label | ...[...] |
1083+
| hash_flow.rb:729:15:729:25 | call to taint : | semmle.label | call to taint : |
1084+
| hash_flow.rb:731:15:731:25 | call to taint : | semmle.label | call to taint : |
1085+
| hash_flow.rb:734:15:734:25 | call to taint : | semmle.label | call to taint : |
1086+
| hash_flow.rb:736:15:736:25 | call to taint : | semmle.label | call to taint : |
1087+
| hash_flow.rb:738:14:738:20 | ** ... [element :a] : | semmle.label | ** ... [element :a] : |
1088+
| hash_flow.rb:738:14:738:20 | ** ... [element :c] : | semmle.label | ** ... [element :c] : |
1089+
| hash_flow.rb:738:16:738:20 | hash1 [element :a] : | semmle.label | hash1 [element :a] : |
1090+
| hash_flow.rb:738:16:738:20 | hash1 [element :c] : | semmle.label | hash1 [element :c] : |
1091+
| hash_flow.rb:738:29:738:39 | call to taint : | semmle.label | call to taint : |
1092+
| hash_flow.rb:738:42:738:48 | ** ... [element :d] : | semmle.label | ** ... [element :d] : |
1093+
| hash_flow.rb:738:42:738:48 | ** ... [element :f] : | semmle.label | ** ... [element :f] : |
1094+
| hash_flow.rb:738:44:738:48 | hash2 [element :d] : | semmle.label | hash2 [element :d] : |
1095+
| hash_flow.rb:738:44:738:48 | hash2 [element :f] : | semmle.label | hash2 [element :f] : |
1096+
| hash_flow.rb:739:10:739:13 | hash [element :a] : | semmle.label | hash [element :a] : |
1097+
| hash_flow.rb:739:10:739:17 | ...[...] | semmle.label | ...[...] |
1098+
| hash_flow.rb:741:10:741:13 | hash [element :c] : | semmle.label | hash [element :c] : |
1099+
| hash_flow.rb:741:10:741:17 | ...[...] | semmle.label | ...[...] |
1100+
| hash_flow.rb:742:10:742:13 | hash [element :d] : | semmle.label | hash [element :d] : |
1101+
| hash_flow.rb:742:10:742:17 | ...[...] | semmle.label | ...[...] |
1102+
| hash_flow.rb:744:10:744:13 | hash [element :f] : | semmle.label | hash [element :f] : |
1103+
| hash_flow.rb:744:10:744:17 | ...[...] | semmle.label | ...[...] |
1104+
| hash_flow.rb:745:10:745:13 | hash [element :g] : | semmle.label | hash [element :g] : |
1105+
| hash_flow.rb:745:10:745:17 | ...[...] | semmle.label | ...[...] |
10651106
subpaths
10661107
#select
10671108
| hash_flow.rb:22:10:22:17 | ...[...] | hash_flow.rb:11:15:11:24 | call to taint : | hash_flow.rb:22:10:22:17 | ...[...] | $@ | hash_flow.rb:11:15:11:24 | call to taint : | call to taint : |
@@ -1229,3 +1270,8 @@ subpaths
12291270
| hash_flow.rb:720:10:720:13 | ...[...] | hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:720:10:720:13 | ...[...] | $@ | hash_flow.rb:715:15:715:25 | call to taint : | call to taint : |
12301271
| hash_flow.rb:722:10:722:13 | ...[...] | hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:722:10:722:13 | ...[...] | $@ | hash_flow.rb:715:15:715:25 | call to taint : | call to taint : |
12311272
| hash_flow.rb:722:10:722:13 | ...[...] | hash_flow.rb:717:15:717:25 | call to taint : | hash_flow.rb:722:10:722:13 | ...[...] | $@ | hash_flow.rb:717:15:717:25 | call to taint : | call to taint : |
1273+
| hash_flow.rb:739:10:739:17 | ...[...] | hash_flow.rb:729:15:729:25 | call to taint : | hash_flow.rb:739:10:739:17 | ...[...] | $@ | hash_flow.rb:729:15:729:25 | call to taint : | call to taint : |
1274+
| hash_flow.rb:741:10:741:17 | ...[...] | hash_flow.rb:731:15:731:25 | call to taint : | hash_flow.rb:741:10:741:17 | ...[...] | $@ | hash_flow.rb:731:15:731:25 | call to taint : | call to taint : |
1275+
| hash_flow.rb:742:10:742:17 | ...[...] | hash_flow.rb:734:15:734:25 | call to taint : | hash_flow.rb:742:10:742:17 | ...[...] | $@ | hash_flow.rb:734:15:734:25 | call to taint : | call to taint : |
1276+
| hash_flow.rb:744:10:744:17 | ...[...] | hash_flow.rb:736:15:736:25 | call to taint : | hash_flow.rb:744:10:744:17 | ...[...] | $@ | hash_flow.rb:736:15:736:25 | call to taint : | call to taint : |
1277+
| hash_flow.rb:745:10:745:17 | ...[...] | hash_flow.rb:738:29:738:39 | call to taint : | hash_flow.rb:745:10:745:17 | ...[...] | $@ | hash_flow.rb:738:29:738:39 | call to taint : | call to taint : |

ruby/ql/test/library-tests/dataflow/hash-flow/hash_flow.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,3 +723,27 @@ def m44(x)
723723
end
724724

725725
m44(:c)
726+
727+
def m45()
728+
hash1 = {
729+
:a => taint(45.1),
730+
:b => 1,
731+
:c => taint(45.2)
732+
}
733+
hash2 = {
734+
:d => taint(45.3),
735+
:e => 2,
736+
:f => taint(45.4)
737+
}
738+
hash = { **hash1, :g => taint(45.5), **hash2, :h => 3 }
739+
sink(hash[:a]) # $ hasValueFlow=45.1
740+
sink(hash[:b])
741+
sink(hash[:c]) # $ hasValueFlow=45.2
742+
sink(hash[:d]) # $ hasValueFlow=45.3
743+
sink(hash[:e])
744+
sink(hash[:f]) # $ hasValueFlow=45.4
745+
sink(hash[:g]) # $ hasValueFlow=45.5
746+
sink(hash[:h])
747+
end
748+
749+
m45()

0 commit comments

Comments
 (0)