On Mon, Sep 28, 2026 at 10:14:16PM +0200, Pavel Sanda wrote:
> I'll keep posting next pacthes for various issues, but should not

Ok, the next one is sort of DOS - we crash on malformed .lyx input.

Essentially, when parsing header the code assumes every " has it's ending " 
counterpart,
but if the .lyx is malformed and EOF is encountered instead of ending " we 
might crash.

The code uncoditionally resizes the token to strip the ending " which is dead
end for an empty string. In case of non empty string we eat one last character
(which is acceptable for malformed input).

Minimal reproducer:
"\r

The first hunk fixes the crash. The second hunk is just safety measure, it 
should
not be possible to reach, but it's the same unsafe construct and the context 
code
could change one day.

Pavel
>From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pavel Sanda <[email protected]>
Date: Sun, 1 Nov 2026 01:28:29 +0100
Subject: [PATCH] Fix crash on a truncated quoted token in the lexer

The code assumes closing quote always exists in .lyx, which might not be case
for malformed input. The trigger for the crash is a quoted token that ends
with an empty buffer at EOF. DoS only, no code execution.

Fix: guard the resize of buff so it is a no-op on an empty buffer. This is
a no-op on every well-formed input. The same unguarded pattern exists in
eatLine(), guarded there as well, although not currently reachable. 

Tier 03 DoS / lexer: guard quoted-token resize against an empty buffer

Assisted-by: Claude Opus 4.8
---
 src/support/Lexer.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/support/Lexer.cpp b/src/support/Lexer.cpp
index 3b46e0bffb..50a0e289b3 100644
--- a/src/support/Lexer.cpp
+++ b/src/support/Lexer.cpp
@@ -352,7 +352,8 @@ bool Lexer::Pimpl::next(bool esc /* = false */)
 					++lineno;
 			}

-			buff.resize(buff.size() - 1);
+			if (!buff.empty())
+				buff.resize(buff.size() - 1);
 			status = LEX_DATA;
 			break;
 		}
@@ -444,7 +445,8 @@ bool Lexer::Pimpl::eatLine()

 	if (c == '\n') {
 		++lineno;
-		buff.resize(buff.size() - 1);
+		if (!buff.empty())
+			buff.resize(buff.size() - 1);
 		status = LEX_DATA;
 		return true;
 	} else if (buff.length() > 0) { // last line
-- 
lyx-devel mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-devel

Reply via email to