@@ -298,16 +298,18 @@ private class CookiesSameSiteProtectionSetting extends Settings::NillableStringl
298298
299299// TODO: initialization hooks, e.g. before_configuration, after_initialize...
300300// TODO: initializers
301- private string getErbFileIdentifier ( ErbFile erbFile ) { result = erbFile .getRelativePath ( ) }
302-
303301/** A synthetic global to represent the value passed to the `locals` argument of a render call for a specific ERB file. */
304302private class LocalAssignsHashSyntheticGlobal extends SummaryComponent:: SyntheticGlobal {
305303 private ErbFile erbFile ;
306304 private string id ;
305+ // Note that we can't use an actual `Rails::RenderCall` here due to problems with non-monotonic recursion
306+ private MethodCall renderCall ;
307307
308308 LocalAssignsHashSyntheticGlobal ( ) {
309309 this = "LocalAssignsHashSyntheticGlobal+" + id and
310- id = getErbFileIdentifier ( erbFile )
310+ id = erbFile .getRelativePath ( ) + "+" + renderCall .getLocation ( ) and
311+ renderCall .getMethodName ( ) = "render" and
312+ RenderCallUtils:: getTemplateFile ( renderCall ) = erbFile
311313 }
312314
313315 /** Gets the `ErbFile` which this locals hash is accessible from. */
@@ -317,7 +319,7 @@ private class LocalAssignsHashSyntheticGlobal extends SummaryComponent::Syntheti
317319 string getId ( ) { result = id }
318320
319321 /** Gets a call to render that can write to this hash. */
320- Rails:: RenderCall getARenderCall ( ) { result . getTemplateFile ( ) = erbFile }
322+ Rails:: RenderCall getARenderCall ( ) { result = renderCall }
321323}
322324
323325/** A summary for `render` calls linked to some specific ERB file. */
@@ -326,7 +328,7 @@ private class RenderLocalsSummary extends SummarizedCallable {
326328
327329 RenderLocalsSummary ( ) { this = "rails_render_locals()" + glob .getId ( ) }
328330
329- override Rails:: RenderCall getACall ( ) { result . getTemplateFile ( ) = glob .getErbFile ( ) }
331+ override Rails:: RenderCall getACall ( ) { result = glob .getARenderCall ( ) }
330332
331333 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
332334 input = "Argument[locals:]" and
@@ -342,7 +344,7 @@ private class AccessLocalsSummary extends SummarizedCallable {
342344 AccessLocalsSummary ( ) { this = "rails_local_assigns()" + glob .getId ( ) }
343345
344346 override MethodCall getACall ( ) {
345- glob .getId ( ) = getErbFileIdentifier ( result .getLocation ( ) .getFile ( ) ) and
347+ glob .getErbFile ( ) = result .getLocation ( ) .getFile ( ) and
346348 result .getMethodName ( ) = "local_assigns"
347349 }
348350
0 commit comments