Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/dsl/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ func (l *Lexer) lexString() string {
if l.ch == '\\' {
str += l.input[position:l.position]
l.readChar() // Skip the backslash
if l.ch == 0 {
// Backslash at end of input (unterminated escape); stop before
// position runs past the input.
break
}
Comment on lines 212 to +219

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Stray backslash leaks into token literal on EOF-after-backslash.

The panic is fixed, but position isn't advanced before the new break, so the final str += l.input[position:l.position] (line 236) re-includes the just-consumed backslash character. For input "\, the returned STRING literal ends up containing a raw \ instead of being clean/empty, silently corrupting the parsed value instead of surfacing malformed input.

🐛 Proposed fix
 			l.readChar() // Skip the backslash
 			if l.ch == 0 {
 				// Backslash at end of input (unterminated escape); stop before
 				// position runs past the input.
+				position = l.position
 				break
 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if l.ch == '\\' {
str += l.input[position:l.position]
l.readChar() // Skip the backslash
if l.ch == 0 {
// Backslash at end of input (unterminated escape); stop before
// position runs past the input.
break
}
if l.ch == '\\' {
str += l.input[position:l.position]
l.readChar() // Skip the backslash
if l.ch == 0 {
// Backslash at end of input (unterminated escape); stop before
// position runs past the input.
position = l.position
break
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/dsl/lexer/lexer.go` around lines 212 - 219, The string scanning logic in
lexer.go’s string-reading path is still re-adding the trailing backslash when
EOF is reached after an escape. Update the branch in the lexer’s string token
accumulation (around the readChar/break handling in the string literal parser)
so the consumed backslash is not included in the final token value; advance the
tracking position before breaking or otherwise exclude that segment from the
final append. Verify the fix in the string token builder used by the lexer so an
input ending with a lone backslash does not return a STRING literal containing a
raw backslash.

switch l.ch {
case 'n':
str += "\n"
Expand Down
9 changes: 9 additions & 0 deletions pkg/dsl/lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1189,4 +1189,13 @@ rule test_rule(created_at time, started_at time) {
Expect(hasBoolean).Should(BeTrue())
Expect(hasComparison).Should(BeTrue())
})

It("Unterminated string ending in a backslash does not panic", func() {
// A quote followed by a trailing backslash reaches EOF mid-escape.
l := NewLexer("\"\\")

var tok token.Token
Expect(func() { tok = l.NextToken() }).ShouldNot(Panic())
Expect(tok.Type).Should(BeEquivalentTo(token.STRING))
})
})
Loading