diff mercurial/templater.py @ 27939:7ed3a3c0cef1 stable

templater: abort if infinite recursion detected while evaluation (issue4758) It would be nice if we could detect recursion at the parsing phase, but we can't because a template can refer to a keyword of the same name. For example, "rev = {rev}" is valid if rev is a keyword, and we don't know if rev is a keyword or a template while parsing.
author Yuya Nishihara <yuya@tcha.org>
date Wed, 22 Jul 2015 23:29:41 +0900
parents 83aef8d5bc1b
children cfe7da66f555
line wrap: on
line diff
--- a/mercurial/templater.py	Fri Jan 22 16:31:50 2016 -0800
+++ b/mercurial/templater.py	Wed Jul 22 23:29:41 2015 +0900
@@ -226,13 +226,22 @@
 def runstring(context, mapping, data):
     return data
 
+def _recursivesymbolblocker(key):
+    def showrecursion(**args):
+        raise error.Abort(_("recursive reference '%s' in template") % key)
+    return showrecursion
+
 def runsymbol(context, mapping, key):
     v = mapping.get(key)
     if v is None:
         v = context._defaults.get(key)
     if v is None:
+        # put poison to cut recursion. we can't move this to parsing phase
+        # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
+        safemapping = mapping.copy()
+        safemapping[key] = _recursivesymbolblocker(key)
         try:
-            v = context.process(key, mapping)
+            v = context.process(key, safemapping)
         except TemplateNotFound:
             v = ''
     if callable(v):