Restore old behavior for \" within interpolations

Before the parser rewrite, HCL would silently convert `\"` within
interpolation braces to `"`.

After the conversion, this became a syntax error.

We've found several instances of Terraform configs in the wild using
this syntax. It results in a hard "syntax error" message during config
parsing. While avoiding the extra escape on double quotes within
interpolations is definitely preferred, the UX of the syntax error feels
harsh enough to be worth inserting this backwards compatibility for now,
leaving us the option of deprecating it with a warning down the line.
This commit is contained in:
Paul Hinze 2015-11-19 11:49:35 -06:00
parent 2deb1d1db2
commit feb701804f
8 changed files with 27 additions and 6 deletions

View File

@ -50,6 +50,13 @@ func TestDecode_interface(t *testing.T) {
"foo": "bar\"baz\\n",
},
},
{
"interpolate_escape.hcl",
false,
map[string]interface{}{
"foo": "${file(\"bing/bong.txt\")}",
},
},
{
"float.hcl",
false,

View File

@ -3,6 +3,8 @@ variable "foo" {
description = "bar"
}
variable "groups" { }
provider "aws" {
access_key = "foo"
secret_key = "bar"
@ -19,8 +21,9 @@ resource "aws_security_group" "firewall" {
resource aws_instance "web" {
ami = "${var.foo}"
security_groups = [
"foo",
"foo",
"${aws_security_group.firewall.foo}",
"${element(split(\",\", var.groups)}",
]
network_interface = {
device_index = 0

View File

@ -79,6 +79,7 @@ var tokenLists = map[string][]tokenPair{
{token.STRING, `"a"`},
{token.STRING, `"本"`},
{token.STRING, `"${file("foo")}"`},
{token.STRING, `"${file(\"foo\")}"`},
{token.STRING, `"\a"`},
{token.STRING, `"\b"`},
{token.STRING, `"\f"`},

View File

@ -49,7 +49,7 @@ func Unquote(s string) (t string, err error) {
for len(s) > 0 {
// If we're starting a '${}' then let it through un-unquoted.
// Specifically: we don't unquote any characters within the `${}`
// section.
// section, except for escaped quotes, which we handle specifically.
if s[0] == '$' && len(s) > 1 && s[1] == '{' {
buf = append(buf, '$', '{')
s = s[2:]
@ -64,6 +64,14 @@ func Unquote(s string) (t string, err error) {
s = s[size:]
// We special case escaped double quotes in interpolations, converting
// them to straight double quotes.
if r == '\\' {
if q, _ := utf8.DecodeRuneInString(s); q == '"' {
continue
}
}
n := utf8.EncodeRune(runeTmp[:], r)
buf = append(buf, runeTmp[:n]...)

View File

@ -1,8 +1,6 @@
package strconv
import (
"testing"
)
import "testing"
type quoteTest struct {
in string
@ -38,6 +36,7 @@ var unquotetests = []unQuoteTest{
{`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""},
{`"'"`, "'"},
{`"${file("foo")}"`, `${file("foo")}`},
{`"${file(\"foo\")}"`, `${file("foo")}`},
}
var misquoted = []string{
@ -72,7 +71,7 @@ var misquoted = []string{
func TestUnquote(t *testing.T) {
for _, tt := range unquotetests {
if out, err := Unquote(tt.in); err != nil && out != tt.out {
if out, err := Unquote(tt.in); err != nil || out != tt.out {
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
}
}

View File

@ -50,6 +50,7 @@ func TestTokenValue(t *testing.T) {
{Token{Type: IDENT, Text: `foo`}, "foo"},
{Token{Type: STRING, Text: `"foo"`}, "foo"},
{Token{Type: STRING, Text: `"foo\nbar"`}, "foo\nbar"},
{Token{Type: STRING, Text: `"${file(\"foo\")}"`}, `${file("foo")}`},
{Token{Type: HEREDOC, Text: "<<EOF\nfoo\nbar\nEOF"}, "foo\nbar"},
}

View File

@ -33,6 +33,7 @@ var tokenLists = map[string][]tokenPair{
{token.STRING, `"a"`},
{token.STRING, `"本"`},
{token.STRING, `"${file("foo")}"`},
{token.STRING, `"${file(\"foo\")}"`},
{token.STRING, `"\a"`},
{token.STRING, `"\b"`},
{token.STRING, `"\f"`},

View File

@ -0,0 +1 @@
foo="${file(\"bing/bong.txt\")}"