From c83a29c27f2297ae19ac58b30a5328b0c11d08f0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 14 Sep 2023 21:19:04 +0200 Subject: [PATCH] Ruby: Fix a bad join Before ``` Evaluated relational algebra for predicate Sinatra#e09174a3::Sinatra::ErbLocalsAccessSummary#fff@22c05bb6 with tuple counts: 212957 ~2195% {1} r1 = JOIN _Constant#54e8b051::ConstantValue::getStringlikeValue#0#dispred#ff_Expr#6fb2af19::Expr::getConstantV__#shared WITH Expr#6fb2af19::Pair::getKey#0#dispred#ff_1#join_rhs ON FIRST 1 OUTPUT Lhs.1 43862468 ~6045% {2} r2 = JOIN r1 WITH Call#841c84e8::MethodCall::getMethodName#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.0 43862468 ~6581% {2} r3 = JOIN r2 WITH AST#a6718388::AstNode::getLocation#0#dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 43844886 ~40661% {2} r4 = JOIN r3 WITH locations_default ON FIRST 1 OUTPUT Rhs.1, Lhs.1 15004 ~8295% {3} r5 = JOIN r4 WITH project#Sinatra#e09174a3::Sinatra::ErbLocalsHashSyntheticGlobal#ffff_201#join_rhs ON FIRST 1 OUTPUT Rhs.2, Lhs.1, Rhs.1 15004 ~8890% {3} r6 = SCAN r5 OUTPUT ("sinatra_erb_locals_access()" ++ In.0 ++ "#" ++ In.1), In.2, In.1 return r6 ``` After ``` Evaluated relational algebra for predicate Sinatra#e09174a3::Sinatra::ErbLocalsAccessSummary#fff@f6249cga with tuple counts: 10237 ~0% {3} r1 = JOIN locations_default_10#join_rhs WITH project#Sinatra#e09174a3::Sinatra::ErbLocalsHashSyntheticGlobal#ffff_201#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Rhs.2 4015 ~5% {3} r2 = JOIN r1 WITH AST#a6718388::AstNode::getLocation#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2 825 ~96% {3} r3 = JOIN r2 WITH Call#841c84e8::MethodCall::getMethodName#0#dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2 940 ~0% {4} r4 = JOIN r3 WITH Constant#54e8b051::ConstantValue::getStringlikeValue#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.0 325402 ~0% {4} r5 = JOIN r4 WITH Expr#6fb2af19::Expr::getConstantValue#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3 231819 ~133147% {3} r6 = JOIN r5 WITH Expr#6fb2af19::Pair::getKey#0#dispred#ff_1#join_rhs ON FIRST 1 OUTPUT Lhs.2, Lhs.3, Lhs.1 231819 ~138805% {3} r7 = SCAN r6 OUTPUT ("sinatra_erb_locals_access()" ++ In.0 ++ "#" ++ In.1), In.2, In.1 return r7 ``` --- ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll b/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll index dcec7524bc23..01795386a30b 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll @@ -179,6 +179,12 @@ module Sinatra { } } + bindingset[local] + pragma[inline_late] + private predicate isPairKey(string local) { + local = any(Pair p).getKey().getConstantValue().getStringlikeValue() + } + /** * A summary for accessing a local variable in an ERB template. * This is the second half of the modeling of the flow from the `locals` @@ -192,7 +198,7 @@ module Sinatra { ErbLocalsAccessSummary() { this = "sinatra_erb_locals_access()" + global.getId() + "#" + local and local = any(MethodCall c | c.getLocation().getFile() = global.getErbFile()).getMethodName() and - local = any(Pair p).getKey().getConstantValue().getStringlikeValue() + isPairKey(local) } override MethodCall getACall() {