@@ -198,33 +198,12 @@ module Filters {
198198
199199 FilterKind getKind ( ) { result = kind }
200200
201- private ModuleBase getEnclosingModule ( ) { result = call .getExpr ( ) .getEnclosingModule ( ) }
202-
203201 /**
204202 * Holds if this callback is registered before `other`. This does not
205203 * guarantee that the callback will be executed before `other`. For example,
206204 * `after_action` callbacks are executed in reverse order.
207205 */
208- predicate registeredBefore ( Filter other ) {
209- // before_action :this, :other
210- //
211- // before_action :this
212- // before_action :other
213- this .getBasicBlock ( ) = other .getBasicBlock ( ) and this .getASuccessor + ( ) = other
214- or
215- this .getEnclosingModule ( ) = other .getEnclosingModule ( ) and
216- this .getBasicBlock ( ) .strictlyDominates ( other .getBasicBlock ( ) ) and
217- this != other
218- or
219- // This callback is in a superclass of `other`'s class.
220- //
221- // class A
222- // before_action :this
223- //
224- // class B < A
225- // before_action :other
226- other .getEnclosingModule ( ) .getModule ( ) = this .getEnclosingModule ( ) .getModule ( ) .getASubClass + ( )
227- }
206+ predicate registeredBefore ( Filter other ) { callbackRegisteredBefore ( call , _, this , other ) }
228207
229208 /**
230209 * Holds if this callback runs before `other`.
@@ -277,7 +256,9 @@ module Filters {
277256 * with the same name is registered later one, overriding this one.
278257 */
279258 predicate skipped ( ActionControllerActionMethod action ) {
280- this = any ( SkipFilter f | f .getKind ( ) = this .getKind ( ) ) .getSkippedFilter ( action ) or
259+ this =
260+ any ( SkipFilter f | f .getKind ( ) = this .getKind ( ) and this .registeredBefore ( f ) )
261+ .getSkippedFilter ( action ) or
281262 this .overridden ( )
282263 }
283264
@@ -339,6 +320,11 @@ module Filters {
339320
340321 ActionControllerActionMethod getAction ( ) { result = call .getAction ( ) }
341322
323+ predicate registeredBefore ( StringlikeLiteralCfgNode other ) {
324+ ( other instanceof SkipFilter or other instanceof Filter ) and
325+ callbackRegisteredBefore ( call , _, this , other )
326+ }
327+
342328 Filter getSkippedFilter ( ActionControllerActionMethod action ) {
343329 not result instanceof SkipFilter and
344330 action = this .getAction ( ) and
@@ -347,6 +333,47 @@ module Filters {
347333 }
348334 }
349335
336+ /**
337+ * Holds if `predCall` (resp. `succCall`) registers or skips the callback referred to by `pred` (`succ`) and `predCall` is evaluated called before `succCall`.
338+ * Typically this means that `pred` is registered before `succ`, or `pred` is skipped before `succ`, depending on the nature of the call.
339+ * `pred` and `succ` are expected to be arguments. In the examples below, `pred` is `:foo` and `succ` is `:bar`.
340+ * ```rb
341+ * before_action :foo, :bar
342+ * skip_before_action :foo, :bar
343+ * ```
344+ * This does not guarantee that the callback referred to by `pred` will be executed before
345+ * `succ`. For example, `after_action` callbacks are executed in reverse order.
346+ */
347+ private predicate callbackRegisteredBefore (
348+ FilterCall predCall , FilterCall succCall , StringlikeLiteralCfgNode pred ,
349+ StringlikeLiteralCfgNode succ
350+ ) {
351+ pred = predCall .getFilterArgument ( ) and
352+ succ = succCall .getFilterArgument ( ) and
353+ (
354+ // before_action :this, :other
355+ //
356+ // before_action :this
357+ // before_action :other
358+ pred .getBasicBlock ( ) = succ .getBasicBlock ( ) and
359+ pred .getASuccessor + ( ) = succ
360+ or
361+ predCall .getExpr ( ) .getEnclosingModule ( ) = succCall .getExpr ( ) .getEnclosingModule ( ) and
362+ pred .getBasicBlock ( ) .strictlyDominates ( succ .getBasicBlock ( ) ) and
363+ pred != succ
364+ or
365+ // This callback is in a superclass of `other`'s class.
366+ //
367+ // class A
368+ // before_action :this
369+ //
370+ // class B < A
371+ // before_action :other
372+ succCall .getExpr ( ) .getEnclosingModule ( ) .getModule ( ) =
373+ predCall .getExpr ( ) .getEnclosingModule ( ) .getModule ( ) .getASubClass + ( )
374+ )
375+ }
376+
350377 /**
351378 * Holds if `pred` is called before `succ` in the callback chain for action `action`.
352379 * `pred` and `succ` may be methods bound to callbacks or controller actions.
@@ -381,6 +408,5 @@ module Filters {
381408 * Holds if `pred` is called before `succ` in the callback chain for some action.
382409 * `pred` and `succ` may be methods bound to callbacks or controller actions.
383410 */
384- cached
385411 predicate next ( Method pred , Method succ ) { next ( _, pred , succ ) }
386412}
0 commit comments