Skip to content

Commit e5f2b90

Browse files
committed
Ruby: Fix bad join in controllerTemplateFile
Before ``` Evaluated relational algebra for predicate ActionController#32b59475::controllerTemplateFile#2#ff@6f4b2395 with tuple counts: 31304524 ~0% {2} r1 = JOIN locations_default_10#join_rhs WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Rhs.1 34453 ~3% {2} r2 = JOIN r1 WITH DataFlowPublic#e1781e31::ModuleNode::getLocation#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 1236 ~0% {2} r3 = JOIN r2 WITH ActionController#32b59475::ActionControllerClass#f ON FIRST 1 OUTPUT Lhs.0, InverseAppend(("" ++ "app/controllers/"),"_controller.rb",Lhs.1) 1236 ~1% {2} r4 = SCAN r3 OUTPUT In.0, ("" ++ "app/views/layouts/" ++ In.1 ++ "%") 1320 ~1% {3} r5 = JOIN r2 WITH ActionController#32b59475::ActionControllerClass#f ON FIRST 1 OUTPUT Lhs.1, Lhs.0, "^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$" 14 ~7% {5} r6 = JOIN r5 WITH PRIMITIVE regexpCapture#bbff ON Lhs.0,Lhs.2 14 ~7% {5} r7 = SELECT r6 ON In.3 = 1 14 ~0% {3} r8 = SCAN r7 OUTPUT In.1, In.4, InverseAppend((In.4 ++ "app/controllers/"),"_controller.rb",In.0) 14 ~0% {2} r9 = SCAN r8 OUTPUT In.0, (In.1 ++ "app/views/layouts/" ++ In.2 ++ "%") 1250 ~1% {2} r10 = r4 UNION r9 8813750 ~2% {3} r11 = JOIN r10 WITH Erb#b2b9e6ed::ErbFile#ff CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1 8813750 ~6% {4} r12 = JOIN r11 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.0, Rhs.1 41 ~6% {4} r13 = SELECT r12 ON In.3 matches In.1 41 ~0% {2} r14 = SCAN r13 OUTPUT In.0, In.2 1236 ~0% {2} r15 = SCAN r3 OUTPUT ("" ++ "app/views/" ++ In.1), In.0 14 ~0% {2} r16 = SCAN r8 OUTPUT (In.1 ++ "app/views/" ++ In.2), In.0 1250 ~0% {2} r17 = r15 UNION r16 581 ~0% {2} r18 = JOIN r17 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 3243 ~2% {2} r19 = JOIN r18 WITH containerparent ON FIRST 1 OUTPUT Rhs.1, Lhs.1 2767 ~0% {2} r20 = JOIN r19 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.0 2808 ~0% {2} r21 = r14 UNION r20 return r21 ``` After ``` Evaluated relational algebra for predicate ActionController#32b59475::controllerTemplateFile#2#ff@4b56c4f9 with tuple counts: 1236 ~0% {2} r1 = SCAN ActionController#32b59475::getActionControllerClassRelativePath#1#ff OUTPUT In.0, InverseAppend(("" ++ "app/controllers/"),"_controller.rb",In.1) 1236 ~0% {2} r2 = SCAN r1 OUTPUT ("" ++ "app/views/" ++ In.1), In.0 1320 ~0% {3} r3 = SCAN ActionController#32b59475::getActionControllerClassRelativePath#1#ff OUTPUT In.0, In.1, "^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$" 14 ~0% {5} r4 = JOIN r3 WITH PRIMITIVE regexpCapture#bbff ON Lhs.1,Lhs.2 14 ~0% {5} r5 = SELECT r4 ON In.3 = 1 14 ~0% {3} r6 = SCAN r5 OUTPUT In.0, In.4, InverseAppend((In.4 ++ "app/controllers/"),"_controller.rb",In.1) 14 ~0% {2} r7 = SCAN r6 OUTPUT (In.1 ++ "app/views/" ++ In.2), In.0 1250 ~0% {2} r8 = r2 UNION r7 581 ~0% {2} r9 = JOIN r8 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 3243 ~0% {2} r10 = JOIN r9 WITH containerparent ON FIRST 1 OUTPUT Rhs.1, Lhs.1 2767 ~0% {2} r11 = JOIN r10 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.0 1236 ~1% {3} r12 = SCAN r1 OUTPUT In.0, "", In.1 1250 ~1% {3} r13 = r12 UNION r6 102500 ~0% {4} r14 = JOIN r13 WITH project#ActionController#32b59475::getErbFileRelativePath#1#ff CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1, Lhs.2 102500 ~0% {5} r15 = JOIN r14 WITH ActionController#32b59475::getErbFileRelativePath#1#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.0 102500 ~0% {4} r16 = JOIN r15 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.4, Lhs.0, (Lhs.2 ++ "app/views/layouts/" ++ Lhs.3 ++ "%") 41 ~0% {4} r17 = SELECT r16 ON In.1 matches In.3 41 ~3% {2} r18 = SCAN r17 OUTPUT In.0, In.2 2808 ~1% {2} r19 = r11 UNION r18 return r19 ```
1 parent 65835cd commit e5f2b90

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,23 @@ ActionControllerClass getAssociatedControllerClass(ErbFile f) {
511511
)
512512
}
513513

514+
pragma[nomagic]
515+
private string getActionControllerClassRelativePath(ActionControllerClass cls) {
516+
result = cls.getLocation().getFile().getRelativePath()
517+
}
518+
519+
pragma[nomagic]
520+
private string getErbFileRelativePath(ErbFile templateFile) {
521+
result = templateFile.getRelativePath() and
522+
result.matches("%app/views/layouts/%")
523+
}
524+
525+
bindingset[result]
526+
pragma[inline_late]
527+
private string getErbFileRelativePathInlineLate(ErbFile templateFile) {
528+
result = getErbFileRelativePath(templateFile)
529+
}
530+
514531
// TODO: improve layout support, e.g. for `layout` method
515532
// https://guides.rubyonrails.org/layouts_and_rendering.html
516533
/**
@@ -522,15 +539,18 @@ ActionControllerClass getAssociatedControllerClass(ErbFile f) {
522539
*/
523540
predicate controllerTemplateFile(ActionControllerClass cls, ErbFile templateFile) {
524541
exists(string sourcePrefix, string subPath, string controllerPath |
525-
controllerPath = cls.getLocation().getFile().getRelativePath() and
542+
controllerPath = getActionControllerClassRelativePath(cls) and
526543
// `sourcePrefix` is either a prefix path ending in a slash, or empty if
527544
// the rails app is at the source root
528545
sourcePrefix = [controllerPath.regexpCapture("^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$", 1), ""] and
529-
controllerPath = sourcePrefix + "app/controllers/" + subPath + "_controller.rb" and
530-
(
531-
sourcePrefix + "app/views/" + subPath = templateFile.getParentContainer().getRelativePath()
532-
or
533-
templateFile.getRelativePath().matches(sourcePrefix + "app/views/layouts/" + subPath + "%")
546+
controllerPath = sourcePrefix + "app/controllers/" + subPath + "_controller.rb"
547+
|
548+
sourcePrefix + "app/views/" + subPath = templateFile.getParentContainer().getRelativePath()
549+
or
550+
exists(string path |
551+
path = getErbFileRelativePath(_) and
552+
path.matches(sourcePrefix + "app/views/layouts/" + subPath + "%") and
553+
path = getErbFileRelativePathInlineLate(templateFile)
534554
)
535555
)
536556
}

0 commit comments

Comments
 (0)