Skip to content

Commit 8f53801

Browse files
committed
Ruby: Cache ActionDispatch IPA types
1 parent 749dc09 commit 8f53801

File tree

1 file changed

+85
-75
lines changed

1 file changed

+85
-75
lines changed

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

Lines changed: 85 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,6 @@ private import codeql.ruby.DataFlow
1010
* Models routing configuration specified using the `ActionDispatch` library, which is part of Rails.
1111
*/
1212
module ActionDispatch {
13-
private newtype TRouteBlock =
14-
TTopLevelRouteBlock(MethodCall routes, MethodCall draw, Block b) {
15-
routes.getMethodName() = "routes" and
16-
draw.getMethodName() = "draw" and
17-
draw.getReceiver() = routes and
18-
draw.getBlock() = b
19-
} or
20-
// constraints(foo: /some_regex/) do
21-
// get "/posts/:foo", to "posts#something"
22-
// end
23-
TConstraintsRouteBlock(RouteBlock parent, MethodCall constraints, Block b) {
24-
parent.getAStmt() = constraints and
25-
constraints.getMethodName() = "constraints" and
26-
constraints.getBlock() = b
27-
} or
28-
// scope(path: "/some_path", module: "some_module") do
29-
// get "/posts/:foo", to "posts#something"
30-
// end
31-
TScopeRouteBlock(RouteBlock parent, MethodCall scope, Block b) {
32-
parent.getAStmt() = scope and scope.getMethodName() = "scope" and scope.getBlock() = b
33-
} or
34-
// resources :articles do
35-
// get "/comments", to "comments#index"
36-
// end
37-
TResourcesRouteBlock(RouteBlock parent, MethodCall resources, Block b) {
38-
parent.getAStmt() = resources and
39-
resources.getMethodName() = "resources" and
40-
resources.getBlock() = b
41-
} or
42-
// A conditional statement guarding some routes.
43-
// We ignore the condition and analyze both branches to obtain as
44-
// much routing information as possible.
45-
TConditionalRouteBlock(RouteBlock parent, ConditionalExpr e) { parent.getAStmt() = e } or
46-
// namespace :admin do
47-
// resources :posts
48-
// end
49-
TNamespaceRouteBlock(RouteBlock parent, MethodCall namespace, Block b) {
50-
parent.getAStmt() = namespace and
51-
namespace.getMethodName() = "namespace" and
52-
namespace.getBlock() = b
53-
}
54-
5513
/**
5614
* A block that defines some routes.
5715
* Route blocks can contribute to the path or controller namespace of their child routes.
@@ -314,39 +272,6 @@ module ActionDispatch {
314272
override Location getLocation() { result = call.getLocation() }
315273
}
316274

317-
/**
318-
* A route configuration. See `Route` for more info
319-
*/
320-
newtype TRoute =
321-
/**
322-
* See `ExplicitRoute`
323-
*/
324-
TExplicitRoute(RouteBlock b, MethodCall m) {
325-
b.getAStmt() = m and m.getMethodName() = anyHttpMethod()
326-
} or
327-
/**
328-
* See `ResourcesRoute`
329-
*/
330-
TResourcesRoute(RouteBlock b, MethodCall m, string action) {
331-
b.getAStmt() = m and
332-
m.getMethodName() = "resources" and
333-
action in ["show", "index", "new", "edit", "create", "update", "destroy"] and
334-
applyActionFilters(m, action)
335-
} or
336-
/**
337-
* See `SingularResourceRoute`
338-
*/
339-
TResourceRoute(RouteBlock b, MethodCall m, string action) {
340-
b.getAStmt() = m and
341-
m.getMethodName() = "resource" and
342-
action in ["show", "new", "edit", "create", "update", "destroy"] and
343-
applyActionFilters(m, action)
344-
} or
345-
/**
346-
* See `MatchRoute`
347-
*/
348-
TMatchRoute(RouteBlock b, MethodCall m) { b.getAStmt() = m and m.getMethodName() = "match" }
349-
350275
/**
351276
* A route configuration. This defines a combination of HTTP method and URL
352277
* path which should be routed to a particular controller-action pair.
@@ -726,6 +651,91 @@ module ActionDispatch {
726651
}
727652
}
728653

654+
import Cached
655+
656+
/**
657+
* This module contains the IPA types backing `RouteBlock` and `Route`, cached for performance.
658+
*/
659+
cached
660+
private module Cached {
661+
cached
662+
newtype TRouteBlock =
663+
TTopLevelRouteBlock(MethodCall routes, MethodCall draw, Block b) {
664+
routes.getMethodName() = "routes" and
665+
draw.getMethodName() = "draw" and
666+
draw.getReceiver() = routes and
667+
draw.getBlock() = b
668+
} or
669+
// constraints(foo: /some_regex/) do
670+
// get "/posts/:foo", to "posts#something"
671+
// end
672+
TConstraintsRouteBlock(RouteBlock parent, MethodCall constraints, Block b) {
673+
parent.getAStmt() = constraints and
674+
constraints.getMethodName() = "constraints" and
675+
constraints.getBlock() = b
676+
} or
677+
// scope(path: "/some_path", module: "some_module") do
678+
// get "/posts/:foo", to "posts#something"
679+
// end
680+
TScopeRouteBlock(RouteBlock parent, MethodCall scope, Block b) {
681+
parent.getAStmt() = scope and scope.getMethodName() = "scope" and scope.getBlock() = b
682+
} or
683+
// resources :articles do
684+
// get "/comments", to "comments#index"
685+
// end
686+
TResourcesRouteBlock(RouteBlock parent, MethodCall resources, Block b) {
687+
parent.getAStmt() = resources and
688+
resources.getMethodName() = "resources" and
689+
resources.getBlock() = b
690+
} or
691+
// A conditional statement guarding some routes.
692+
// We ignore the condition and analyze both branches to obtain as
693+
// much routing information as possible.
694+
TConditionalRouteBlock(RouteBlock parent, ConditionalExpr e) { parent.getAStmt() = e } or
695+
// namespace :admin do
696+
// resources :posts
697+
// end
698+
TNamespaceRouteBlock(RouteBlock parent, MethodCall namespace, Block b) {
699+
parent.getAStmt() = namespace and
700+
namespace.getMethodName() = "namespace" and
701+
namespace.getBlock() = b
702+
}
703+
704+
/**
705+
* A route configuration. See `Route` for more info
706+
*/
707+
cached
708+
newtype TRoute =
709+
/**
710+
* See `ExplicitRoute`
711+
*/
712+
TExplicitRoute(RouteBlock b, MethodCall m) {
713+
b.getAStmt() = m and m.getMethodName() = anyHttpMethod()
714+
} or
715+
/**
716+
* See `ResourcesRoute`
717+
*/
718+
TResourcesRoute(RouteBlock b, MethodCall m, string action) {
719+
b.getAStmt() = m and
720+
m.getMethodName() = "resources" and
721+
action in ["show", "index", "new", "edit", "create", "update", "destroy"] and
722+
applyActionFilters(m, action)
723+
} or
724+
/**
725+
* See `SingularResourceRoute`
726+
*/
727+
TResourceRoute(RouteBlock b, MethodCall m, string action) {
728+
b.getAStmt() = m and
729+
m.getMethodName() = "resource" and
730+
action in ["show", "new", "edit", "create", "update", "destroy"] and
731+
applyActionFilters(m, action)
732+
} or
733+
/**
734+
* See `MatchRoute`
735+
*/
736+
TMatchRoute(RouteBlock b, MethodCall m) { b.getAStmt() = m and m.getMethodName() = "match" }
737+
}
738+
729739
/**
730740
* Several routing methods support the keyword arguments `only:` and `except:`.
731741
* - `only:` restricts the set of actions to just those in the argument.

0 commit comments

Comments
 (0)