fix(config): Handle escaping and quotation correctly (#13675)

This commit is contained in:
Sven Rebhan 2023-07-26 17:46:14 +02:00 committed by GitHub
parent da28cfdb43
commit cb0bd849ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 6 deletions

View File

@ -807,8 +807,8 @@ func removeComments(contents []byte) ([]byte, error) {
tomlReader := bytes.NewReader(contents)
// Initialize variables for tracking state
var inQuote, inComment bool
var quoteChar, prevChar byte
var inQuote, inComment, escaped bool
var quoteChar byte
// Initialize buffer for modified TOML data
var output bytes.Buffer
@ -825,6 +825,11 @@ func removeComments(contents []byte) ([]byte, error) {
}
char := buf[0]
// Toggle the escaped state at backslash to we have true every odd occurrence.
if char == '\\' {
escaped = !escaped
}
if inComment {
// If we're currently in a comment, check if this character ends the comment
if char == '\n' {
@ -834,26 +839,30 @@ func removeComments(contents []byte) ([]byte, error) {
}
} else if inQuote {
// If we're currently in a quote, check if this character ends the quote
if char == quoteChar && prevChar != '\\' {
if char == quoteChar && !escaped {
// End of quote, we're no longer in a quote
inQuote = false
}
output.WriteByte(char)
} else {
// Not in a comment or a quote
if char == '"' || char == '\'' {
if (char == '"' || char == '\'') && !escaped {
// Start of quote
inQuote = true
quoteChar = char
output.WriteByte(char)
} else if char == '#' {
} else if char == '#' && !escaped {
// Start of comment
inComment = true
} else {
// Not a comment or a quote, just output the character
output.WriteByte(char)
}
prevChar = char
}
// Reset escaping if any other character occurred
if char != '\\' {
escaped = false
}
}
return output.Bytes(), nil

View File

@ -302,6 +302,55 @@ func TestEnvironmentSubstitutionNewBehavior(t *testing.T) {
}
}
func TestParseConfig(t *testing.T) {
tests := []struct {
name string
setEnv func(*testing.T)
contents string
expected string
errmsg string
}{
{
name: "empty var name",
contents: `
# Environment variables can be used anywhere in this config file, simply surround
# them with ${}. For strings the variable must be within quotes (ie, "${STR_VAR}"),
# for numbers and booleans they should be plain (ie, ${INT_VAR}, ${BOOL_VAR})Should output ${NOT_SET:-${FALLBACK}}
`,
expected: "\n\n\n\n",
},
{
name: "comment in command (issue #13643)",
contents: `
[[inputs.exec]]
commands = ["echo \"abc#def\""]
`,
expected: `
[[inputs.exec]]
commands = ["echo \"abc#def\""]
`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.setEnv != nil {
tt.setEnv(t)
}
tbl, err := parseConfig([]byte(tt.contents))
if tt.errmsg != "" {
require.ErrorContains(t, err, tt.errmsg)
return
}
require.NoError(t, err)
if len(tt.expected) > 0 {
require.EqualValues(t, tt.expected, string(tbl.Data))
}
})
}
}
func TestURLRetries3Fails(t *testing.T) {
httpLoadConfigRetryInterval = 0 * time.Second
responseCounter := 0