fix(config): Handle escaping and quotation correctly (#13675)
This commit is contained in:
parent
da28cfdb43
commit
cb0bd849ad
|
|
@ -807,8 +807,8 @@ func removeComments(contents []byte) ([]byte, error) {
|
||||||
tomlReader := bytes.NewReader(contents)
|
tomlReader := bytes.NewReader(contents)
|
||||||
|
|
||||||
// Initialize variables for tracking state
|
// Initialize variables for tracking state
|
||||||
var inQuote, inComment bool
|
var inQuote, inComment, escaped bool
|
||||||
var quoteChar, prevChar byte
|
var quoteChar byte
|
||||||
|
|
||||||
// Initialize buffer for modified TOML data
|
// Initialize buffer for modified TOML data
|
||||||
var output bytes.Buffer
|
var output bytes.Buffer
|
||||||
|
|
@ -825,6 +825,11 @@ func removeComments(contents []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
char := buf[0]
|
char := buf[0]
|
||||||
|
|
||||||
|
// Toggle the escaped state at backslash to we have true every odd occurrence.
|
||||||
|
if char == '\\' {
|
||||||
|
escaped = !escaped
|
||||||
|
}
|
||||||
|
|
||||||
if inComment {
|
if inComment {
|
||||||
// If we're currently in a comment, check if this character ends the comment
|
// If we're currently in a comment, check if this character ends the comment
|
||||||
if char == '\n' {
|
if char == '\n' {
|
||||||
|
|
@ -834,26 +839,30 @@ func removeComments(contents []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
} else if inQuote {
|
} else if inQuote {
|
||||||
// If we're currently in a quote, check if this character ends the quote
|
// 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
|
// End of quote, we're no longer in a quote
|
||||||
inQuote = false
|
inQuote = false
|
||||||
}
|
}
|
||||||
output.WriteByte(char)
|
output.WriteByte(char)
|
||||||
} else {
|
} else {
|
||||||
// Not in a comment or a quote
|
// Not in a comment or a quote
|
||||||
if char == '"' || char == '\'' {
|
if (char == '"' || char == '\'') && !escaped {
|
||||||
// Start of quote
|
// Start of quote
|
||||||
inQuote = true
|
inQuote = true
|
||||||
quoteChar = char
|
quoteChar = char
|
||||||
output.WriteByte(char)
|
output.WriteByte(char)
|
||||||
} else if char == '#' {
|
} else if char == '#' && !escaped {
|
||||||
// Start of comment
|
// Start of comment
|
||||||
inComment = true
|
inComment = true
|
||||||
} else {
|
} else {
|
||||||
// Not a comment or a quote, just output the character
|
// Not a comment or a quote, just output the character
|
||||||
output.WriteByte(char)
|
output.WriteByte(char)
|
||||||
}
|
}
|
||||||
prevChar = char
|
}
|
||||||
|
|
||||||
|
// Reset escaping if any other character occurred
|
||||||
|
if char != '\\' {
|
||||||
|
escaped = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output.Bytes(), nil
|
return output.Bytes(), nil
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func TestURLRetries3Fails(t *testing.T) {
|
||||||
httpLoadConfigRetryInterval = 0 * time.Second
|
httpLoadConfigRetryInterval = 0 * time.Second
|
||||||
responseCounter := 0
|
responseCounter := 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue