Fix inverted bounds check dropping every Erlang string with a backslash (#5110)

parseErlangString advances past a backslash escape and then checks
len(data) >= *i before reading the escaped byte. That condition is
almost always true (it only turns false once *i runs off the end),
so the intended out-of-range guard fires on the very first escape
character it sees instead of only at EOF. Any rebar.lock or OTP
resource file containing a backslash in a quoted string (a Windows
git path, an escaped quote, anything) fails to parse and the whole
file, and every package in it, gets dropped.

Flip the comparison to *i >= len(data) so the guard only trips when
the escape is genuinely truncated, and add a regression test for a
string with an escaped quote.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
This commit is contained in:
Arpit Jain 2026-07-27 23:22:41 +09:00 committed by GitHub
parent 138d9ce2a0
commit 12b8ba47fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 1 deletions

View File

@ -156,7 +156,7 @@ func parseErlangString(data []byte, i *int) (erlangNode, error) {
} }
if c == '\\' { if c == '\\' {
*i++ *i++
if len(data) >= *i { if *i >= len(data) {
return node(nil), fmt.Errorf("invalid escape without closed string at %d", *i) return node(nil), fmt.Errorf("invalid escape without closed string at %d", *i)
} }
c = data[*i] c = data[*i]

View File

@ -96,6 +96,11 @@ func Test_parseErlang(t *testing.T) {
{ foo, bar } { foo, bar }
]}`, ]}`,
}, },
{
name: "string with an escaped quote",
content: `
{escaped, ["a\"b"]}`,
},
} }
for _, test := range tests { for _, test := range tests {
@ -112,3 +117,14 @@ func Test_parseErlang(t *testing.T) {
}) })
} }
} }
func Test_parseErlangString_escapedByte(t *testing.T) {
// a backslash escape mid-string used to always error out, since the bounds
// check at the escape site was inverted (len(data) >= *i is true for
// almost every position, not just an out-of-range one).
data := []byte(`"a\"b"`)
i := 0
got, err := parseErlangString(data, &i)
require.NoError(t, err)
assert.Equal(t, `a"b`, got.String())
}