Skip to content

Commit

Permalink
Make parser more strict
Browse files Browse the repository at this point in the history
- It will now error if you have characters after the end of a quoted string, i.e. `"key"bad=val` or `key="val"bad`
- It will now error if there is an empty key
- Fixed a minor bug with the calculation of the location of the error, it was not counting quotes properly before

Signed-off-by: Daniel Mikusa <[email protected]>
  • Loading branch information
Daniel Mikusa committed Oct 21, 2021
1 parent 2bc8f9b commit edea117
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
31 changes: 22 additions & 9 deletions labels/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ func ReadKey(buf string) (string, string, error) {

// end quote
if (ch == '"' || ch == '\'') && needClosingQuote {
// throw out anything between closing quote and equals sign
_, rest, _ = ReadToNext(rest, `=`)
invalid, rest, _ := ReadToNext(rest, `=`)
if len(strings.TrimSpace(invalid)) > 0 {
return "", rest, fmt.Errorf("unable to have characters after a trailing quote")
}
return item, rest, nil
}

Expand All @@ -121,7 +123,7 @@ func ReadKey(buf string) (string, string, error) {

// end of key or no more data
if (ch == '=' || rest == "") && needClosingQuote {
return item, rest, fmt.Errorf("unable to find a closing quote")
return "", rest, fmt.Errorf("unable to find a closing quote")
} else if ch == '=' || rest == "" {
return item, rest, nil
}
Expand Down Expand Up @@ -155,8 +157,10 @@ func ReadValue(buf string) (string, string, error) {

// end quote
if (ch == '"' || ch == '\'') && needClosingQuote {
// throw out anything between closing quote and equals sign
_, rest, _ = ReadToNext(rest, ` `)
invalid, rest, _ := ReadToNext(rest, ` `)
if len(strings.TrimSpace(invalid)) > 0 {
return "", rest, fmt.Errorf("unable to have characters after a trailing quote")
}
return item, rest, nil
}

Expand All @@ -177,7 +181,7 @@ func ReadValue(buf string) (string, string, error) {

// end of data buffer
if rest == "" && needClosingQuote {
return item, rest, fmt.Errorf("unable to find a closing quote")
return "", rest, fmt.Errorf("unable to find a closing quote")
} else if rest == "" {
return item, rest, nil
}
Expand All @@ -196,17 +200,26 @@ func ParseLabels(rest string) (map[string]string, error) {
)

for {
before := len(rest)
key, rest, err = ReadKey(rest)
pos += len(key) + 1
pos += before - len(rest)

if err != nil {
return nil, fmt.Errorf("unable to read key ending at char %d\n%w", pos, err)
return nil, fmt.Errorf("unable to read key ending at char %d\n%w", pos-1, err)
}

if len(key) == 0 {
return nil, fmt.Errorf("unable to have empty key ending at char %d", pos-1)
}

before = len(rest)
val, rest, err = ReadValue(rest)
pos += len(val) + 1
pos += before - len(rest)

if err != nil {
if len(rest) > 0 {
pos -= 1
}
return nil, fmt.Errorf("unable to read value ending at char %d\n%w", pos, err)
}

Expand Down
24 changes: 23 additions & 1 deletion labels/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {

it("parses a complex label", func() {
assertMap(`some-label=(example)value some-label-2=""hi there" test='hi'`,
nil, "unable to read key ending at char 51")
nil, "unable to read value ending at char 43\nunable to have characters after a trailing quote")
})

it("parses with embedded equal signs", func() {
Expand All @@ -277,6 +277,28 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
assertMap(`foo="bar=baz"`,
map[string]string{"foo": "bar=baz"}, "")
})

it("fails on an empty key", func() {
assertMap(`""=bar`,
nil, "unable to have empty key ending at char 2")
})

it("fails if characters after a quote", func() {
assertMap(`"foo"junk=bar`,
nil, "unable to read key ending at char 9\nunable to have characters after a trailing quote")
assertMap(`foo="bar"junk`,
nil, "unable to read value ending at char 13\nunable to have characters after a trailing quote")
})

it("parses complicated statement", func() {
assertMap(`some-label=(example)value some-label-2=""hi t""here="" test=\'hi\'`,
nil, "unable to read value ending at char 43\nunable to have characters after a trailing quote")
})

it("parses complicated statement", func() {
assertMap(`some-label=(example)value some-label-2="hi t"here="" test=\'hi\'`,
nil, "unable to read value ending at char 52\nunable to have characters after a trailing quote")
})
})

}

0 comments on commit edea117

Please sign in to comment.