From 4b44cb1a78e7cfc512f69f2cdc4ba9d0359d99d9 Mon Sep 17 00:00:00 2001 From: Daniel Sun Date: Fri, 6 Apr 2018 21:44:49 +0800 Subject: [PATCH] GROOVY-4585: backslash can not be escaped by `SimpleTemplateEngine` --- .../groovy/bugs/groovy4585/groovy4585.xml | 12 ++++++ .../bugs/groovy4585/Groovy4585Bug.groovy | 33 ++++++++++++++++ .../groovy/text/SimpleTemplateEngine.java | 38 ++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/test-resources/groovy/bugs/groovy4585/groovy4585.xml create mode 100644 src/test/groovy/bugs/groovy4585/Groovy4585Bug.groovy diff --git a/src/test-resources/groovy/bugs/groovy4585/groovy4585.xml b/src/test-resources/groovy/bugs/groovy4585/groovy4585.xml new file mode 100644 index 00000000000..5d8e83ce2af --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4585/groovy4585.xml @@ -0,0 +1,12 @@ + + + + + + <%for (int i = 0; i < names.size(); i++) {%> + + + + <%}%> + + diff --git a/src/test/groovy/bugs/groovy4585/Groovy4585Bug.groovy b/src/test/groovy/bugs/groovy4585/Groovy4585Bug.groovy new file mode 100644 index 00000000000..fed604ebe10 --- /dev/null +++ b/src/test/groovy/bugs/groovy4585/Groovy4585Bug.groovy @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package groovy.bugs.groovy4585 + +class Groovy4585Bug extends GroovyTestCase { + void test() { + assertScript ''' + package groovy.bugs.groovy4585 + def engineForBuildXml = new groovy.text.SimpleTemplateEngine(false, true) + def templateForBuildXml = engineForBuildXml.createTemplate(this.getClass().getResource("/groovy/bugs/groovy4585/groovy4585.xml").text) + String buildXmlContent = templateForBuildXml.make([names:['a', 'b', 'c']]).toString() + + assert buildXmlContent.contains('') + assert buildXmlContent.contains('') + ''' + } +} diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/SimpleTemplateEngine.java b/subprojects/groovy-templates/src/main/groovy/groovy/text/SimpleTemplateEngine.java index e4776aba5c6..2c541f09c19 100644 --- a/subprojects/groovy-templates/src/main/groovy/groovy/text/SimpleTemplateEngine.java +++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/SimpleTemplateEngine.java @@ -97,16 +97,21 @@ public class SimpleTemplateEngine extends TemplateEngine { private boolean verbose; private static int counter = 1; - private GroovyShell groovyShell; + private boolean escapeBackslash; public SimpleTemplateEngine() { this(GroovyShell.class.getClassLoader()); } public SimpleTemplateEngine(boolean verbose) { + this(verbose, false); + } + + public SimpleTemplateEngine(boolean verbose, boolean escapeBackslash) { this(GroovyShell.class.getClassLoader()); setVerbose(verbose); + this.escapeBackslash = escapeBackslash; } public SimpleTemplateEngine(ClassLoader parentLoader) { @@ -118,7 +123,7 @@ public SimpleTemplateEngine(GroovyShell groovyShell) { } public Template createTemplate(Reader reader) throws CompilationFailedException, IOException { - SimpleTemplate template = new SimpleTemplate(); + SimpleTemplate template = new SimpleTemplate(escapeBackslash); String script = template.parse(reader); if (verbose) { System.out.println("\n-- script source --"); @@ -147,6 +152,16 @@ public boolean isVerbose() { private static class SimpleTemplate implements Template { protected Script script; + private boolean escapeBackslash; + + public SimpleTemplate() { + this(false); + } + + public SimpleTemplate(boolean escapeBackslash) { + this.escapeBackslash = escapeBackslash; + } + public Writable make() { return make(null); @@ -236,6 +251,25 @@ protected String parse(Reader reader) throws IOException { if (c == '\"') { sw.write('\\'); } + + /* + * GROOVY-4585 + * Handle backslash characters. + */ + if (escapeBackslash) { + if (c == '\\') { + reader.mark(1); + c = reader.read(); + if (c != '$') { + sw.write("\\\\"); + reader.reset(); + } else { + sw.write("\\$"); + } + + continue; + } + } /* * Handle raw new line characters. */