Mercurial > public > mercurial-scm > hg
comparison mercurial/templater.py @ 27940:cfe7da66f555 stable
templater: abort if infinite recursion detected while compiling
In this case, a template is parsed recursively with no thunk for lazy
evaluation. This patch prevents recursion by putting a dummy of the same name
into a cache that will be referenced while parsing if there's a recursion.
changeset = {files % changeset}\n
~~~~~~~~~
= [(_runrecursivesymbol, 'changeset')]
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 23 Jul 2015 23:41:29 +0900 |
parents | 7ed3a3c0cef1 |
children | 96f2d50fb9f6 |
comparison
equal
deleted
inserted
replaced
27939:7ed3a3c0cef1 | 27940:cfe7da66f555 |
---|---|
229 def _recursivesymbolblocker(key): | 229 def _recursivesymbolblocker(key): |
230 def showrecursion(**args): | 230 def showrecursion(**args): |
231 raise error.Abort(_("recursive reference '%s' in template") % key) | 231 raise error.Abort(_("recursive reference '%s' in template") % key) |
232 return showrecursion | 232 return showrecursion |
233 | 233 |
234 def _runrecursivesymbol(context, mapping, key): | |
235 raise error.Abort(_("recursive reference '%s' in template") % key) | |
236 | |
234 def runsymbol(context, mapping, key): | 237 def runsymbol(context, mapping, key): |
235 v = mapping.get(key) | 238 v = mapping.get(key) |
236 if v is None: | 239 if v is None: |
237 v = context._defaults.get(key) | 240 v = context._defaults.get(key) |
238 if v is None: | 241 if v is None: |
824 self._cache = {} | 827 self._cache = {} |
825 | 828 |
826 def _load(self, t): | 829 def _load(self, t): |
827 '''load, parse, and cache a template''' | 830 '''load, parse, and cache a template''' |
828 if t not in self._cache: | 831 if t not in self._cache: |
829 self._cache[t] = compiletemplate(self._loader(t), self) | 832 # put poison to cut recursion while compiling 't' |
833 self._cache[t] = [(_runrecursivesymbol, t)] | |
834 try: | |
835 self._cache[t] = compiletemplate(self._loader(t), self) | |
836 except: # re-raises | |
837 del self._cache[t] | |
838 raise | |
830 return self._cache[t] | 839 return self._cache[t] |
831 | 840 |
832 def process(self, t, mapping): | 841 def process(self, t, mapping): |
833 '''Perform expansion. t is name of map element to expand. | 842 '''Perform expansion. t is name of map element to expand. |
834 mapping contains added elements for use during expansion. Is a | 843 mapping contains added elements for use during expansion. Is a |