Patchwork [1,of,3] templater: avoid recursive evaluation of string literals completely

login
register
mail settings
Submitter Katsunori FUJIWARA
Date March 9, 2014, 4:09 p.m.
Message ID <7e627fe63e5e74b0b694.1394381363@feefifofum>
Download mbox | patch
Permalink /patch/3902/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - March 9, 2014, 4:09 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1394380902 -32400
#      Mon Mar 10 01:01:42 2014 +0900
# Branch stable
# Node ID 7e627fe63e5e74b0b694030957c49d727ec79ba6
# Parent  2d183dd5438450e465785b2204e406ed48e6d5f8
templater: avoid recursive evaluation of string literals completely

Changeset 3d8bfe2ecf6d (released with 2.8.1) fixed "recursively
evaluate string literals as templates" problem (issue4103) by
introducing "_evalifliteral()".

But some parts in template expressions below are still processed by
the combination of "compiletemplate()" and "runtemplate()", and may
cause same problem unexpectedly.

  - 'init' and 'hang' of 'fill(text, width, init, hang)'
  - 'expr' of 'sub(pat, repl, expr)'
  - 'label' of 'label(label, expr)'

This patch processes them by "_evalifliteral()" instead of the
combination of "compiletemplate()" and "runtemplate()" to avoid
recursive evaluation of string literals completely.
Katsunori FUJIWARA - March 9, 2014, 5:31 p.m.
At Mon, 10 Mar 2014 01:09:23 +0900,
FUJIWARA Katsunori wrote:
> 
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1394380902 -32400
> #      Mon Mar 10 01:01:42 2014 +0900
> # Branch stable
> # Node ID 7e627fe63e5e74b0b694030957c49d727ec79ba6
> # Parent  2d183dd5438450e465785b2204e406ed48e6d5f8
> templater: avoid recursive evaluation of string literals completely

Oops, I forgot to add STABLE flag to this bugfix series, sorry.

Please treat this series as so.


> Changeset 3d8bfe2ecf6d (released with 2.8.1) fixed "recursively
> evaluate string literals as templates" problem (issue4103) by
> introducing "_evalifliteral()".
> 
> But some parts in template expressions below are still processed by
> the combination of "compiletemplate()" and "runtemplate()", and may
> cause same problem unexpectedly.
> 
>   - 'init' and 'hang' of 'fill(text, width, init, hang)'
>   - 'expr' of 'sub(pat, repl, expr)'
>   - 'label' of 'label(label, expr)'
> 
> This patch processes them by "_evalifliteral()" instead of the
> combination of "compiletemplate()" and "runtemplate()" to avoid
> recursive evaluation of string literals completely.
> 
> diff --git a/hgext/color.py b/hgext/color.py
> --- a/hgext/color.py
> +++ b/hgext/color.py
> @@ -393,9 +393,7 @@
>      if isinstance(repo, str):
>          return thing
>  
> -    label = templater.stringify(args[0][0](context, mapping, args[0][1]))
> -    label = templater.runtemplate(context, mapping,
> -                                  templater.compiletemplate(label, context))
> +    label = templater._evalifliteral(args[0], context, mapping)
>  
>      thing = templater.stringify(thing)
>      label = templater.stringify(label)
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -234,12 +234,8 @@
>          except ValueError:
>              raise error.ParseError(_("fill expects an integer width"))
>          try:
> -            initindent = stringify(args[2][0](context, mapping, args[2][1]))
> -            initindent = stringify(runtemplate(context, mapping,
> -                                     compiletemplate(initindent, context)))
> -            hangindent = stringify(args[3][0](context, mapping, args[3][1]))
> -            hangindent = stringify(runtemplate(context, mapping,
> -                                     compiletemplate(hangindent, context)))
> +            initindent = stringify(_evalifliteral(args[2], context, mapping))
> +            hangindent = stringify(_evalifliteral(args[3], context, mapping))
>          except IndexError:
>              pass
>  
> @@ -345,9 +341,7 @@
>  
>      pat = stringify(args[0][0](context, mapping, args[0][1]))
>      rpl = stringify(args[1][0](context, mapping, args[1][1]))
> -    src = stringify(args[2][0](context, mapping, args[2][1]))
> -    src = stringify(runtemplate(context, mapping,
> -                                compiletemplate(src, context)))
> +    src = stringify(_evalifliteral(args[2], context, mapping))
>      yield re.sub(pat, rpl, src)
>  
>  methods = {
> diff --git a/tests/test-command-template.t b/tests/test-command-template.t
> --- a/tests/test-command-template.t
> +++ b/tests/test-command-template.t
> @@ -1622,6 +1622,39 @@
>    $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
>    test 0
>  
> +  $ hg branch -q 'text.{rev}'
> +  $ echo aa >> aa
> +  $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
> +
> +  $ hg log -r 1 --template '{fill(desc, "20", author, branch)}'
> +  {node|short}desc to
> +  text.{rev}be wrapped
> +  text.{rev}desc to be
> +  text.{rev}wrapped (no-eol)
> +  $ hg log -r 1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
> +  bcc7ff960b8e:desc to
> +  text.1:be wrapped
> +  text.1:desc to be
> +  text.1:wrapped (no-eol)
> +
> +  $ hg log -r 1 --template '{sub(r"[0-9]", "-", author)}'
> +  {node|short} (no-eol)
> +  $ hg log -r 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
> +  bcc-ff---b-e (no-eol)
> +
> +  $ cat >> .hg/hgrc <<EOF
> +  > [extensions]
> +  > color=
> +  > [color]
> +  > mode=ansi
> +  > text.{rev} = red
> +  > text.1 = green
> +  > EOF
> +  $ hg log --color=always -r 1 --template '{label(branch, "text\n")}'
> +  \x1b[0;31mtext\x1b[0m (esc)
> +  $ hg log --color=always -r 1 --template '{label("text.{rev}", "text\n")}'
> +  \x1b[0;32mtext\x1b[0m (esc)
> +
>  Test branches inside if statement:
>  
>    $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
> 

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy@lares.dti.ne.jp

Patch

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -393,9 +393,7 @@ 
     if isinstance(repo, str):
         return thing
 
-    label = templater.stringify(args[0][0](context, mapping, args[0][1]))
-    label = templater.runtemplate(context, mapping,
-                                  templater.compiletemplate(label, context))
+    label = templater._evalifliteral(args[0], context, mapping)
 
     thing = templater.stringify(thing)
     label = templater.stringify(label)
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -234,12 +234,8 @@ 
         except ValueError:
             raise error.ParseError(_("fill expects an integer width"))
         try:
-            initindent = stringify(args[2][0](context, mapping, args[2][1]))
-            initindent = stringify(runtemplate(context, mapping,
-                                     compiletemplate(initindent, context)))
-            hangindent = stringify(args[3][0](context, mapping, args[3][1]))
-            hangindent = stringify(runtemplate(context, mapping,
-                                     compiletemplate(hangindent, context)))
+            initindent = stringify(_evalifliteral(args[2], context, mapping))
+            hangindent = stringify(_evalifliteral(args[3], context, mapping))
         except IndexError:
             pass
 
@@ -345,9 +341,7 @@ 
 
     pat = stringify(args[0][0](context, mapping, args[0][1]))
     rpl = stringify(args[1][0](context, mapping, args[1][1]))
-    src = stringify(args[2][0](context, mapping, args[2][1]))
-    src = stringify(runtemplate(context, mapping,
-                                compiletemplate(src, context)))
+    src = stringify(_evalifliteral(args[2], context, mapping))
     yield re.sub(pat, rpl, src)
 
 methods = {
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -1622,6 +1622,39 @@ 
   $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
   test 0
 
+  $ hg branch -q 'text.{rev}'
+  $ echo aa >> aa
+  $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
+
+  $ hg log -r 1 --template '{fill(desc, "20", author, branch)}'
+  {node|short}desc to
+  text.{rev}be wrapped
+  text.{rev}desc to be
+  text.{rev}wrapped (no-eol)
+  $ hg log -r 1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
+  bcc7ff960b8e:desc to
+  text.1:be wrapped
+  text.1:desc to be
+  text.1:wrapped (no-eol)
+
+  $ hg log -r 1 --template '{sub(r"[0-9]", "-", author)}'
+  {node|short} (no-eol)
+  $ hg log -r 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
+  bcc-ff---b-e (no-eol)
+
+  $ cat >> .hg/hgrc <<EOF
+  > [extensions]
+  > color=
+  > [color]
+  > mode=ansi
+  > text.{rev} = red
+  > text.1 = green
+  > EOF
+  $ hg log --color=always -r 1 --template '{label(branch, "text\n")}'
+  \x1b[0;31mtext\x1b[0m (esc)
+  $ hg log --color=always -r 1 --template '{label("text.{rev}", "text\n")}'
+  \x1b[0;32mtext\x1b[0m (esc)
+
 Test branches inside if statement:
 
   $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'