From 12b8ba47fbdf146db769377559649b002810f37e Mon Sep 17 00:00:00 2001 From: Arpit Jain <3242828+arpitjain099@users.noreply.github.com> Date: Mon, 27 Jul 2026 23:22:41 +0900 Subject: [PATCH] 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 --- syft/pkg/cataloger/erlang/erlang_parser.go | 2 +- syft/pkg/cataloger/erlang/erlang_parser_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/erlang/erlang_parser.go b/syft/pkg/cataloger/erlang/erlang_parser.go index ae22589b4..819c3bb41 100644 --- a/syft/pkg/cataloger/erlang/erlang_parser.go +++ b/syft/pkg/cataloger/erlang/erlang_parser.go @@ -156,7 +156,7 @@ func parseErlangString(data []byte, i *int) (erlangNode, error) { } if c == '\\' { *i++ - if len(data) >= *i { + if *i >= len(data) { return node(nil), fmt.Errorf("invalid escape without closed string at %d", *i) } c = data[*i] diff --git a/syft/pkg/cataloger/erlang/erlang_parser_test.go b/syft/pkg/cataloger/erlang/erlang_parser_test.go index adb031ddb..9b6950793 100644 --- a/syft/pkg/cataloger/erlang/erlang_parser_test.go +++ b/syft/pkg/cataloger/erlang/erlang_parser_test.go @@ -96,6 +96,11 @@ func Test_parseErlang(t *testing.T) { { foo, bar } ]}`, }, + { + name: "string with an escaped quote", + content: ` +{escaped, ["a\"b"]}`, + }, } 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()) +}