LibJS: Fix syntax highlighter position starting at invalid sentinel

The RehighlightState designated initializer used `.position = {}`
which invokes TextPosition's default constructor, initializing line
and column to 0xFFFFFFFF (the "invalid" sentinel). This overrode
the struct's default member initializer of { 0, 0 }.

When advance_position() processed the first newline, it incremented
0xFFFFFFFF to 0x100000000, producing line numbers in the billions.
These bogus positions propagated into folding regions, causing an
out-of-bounds crash in Document::set_folding_regions() when viewing
page source on pages with <script> blocks.

Fix by explicitly initializing position to { 0, 0 }.

Fixes #8529.
This commit is contained in:
Andreas Kling 2026-03-20 08:26:00 -05:00 committed by Jelle Raaijmakers
parent 6f226f3d2e
commit 943319453d
3 changed files with 21 additions and 1 deletions

View file

@ -139,7 +139,7 @@ void SyntaxHighlighter::rehighlight(Palette const& palette)
.spans = spans,
.folding_regions = folding_regions,
.source = source_data,
.position = {},
.position = { 0, 0 },
.folding_region_starts = {},
};

View file

@ -11,6 +11,7 @@ set(TEST_SOURCES
TestMicrosyntax.cpp
TestMimeSniff.cpp
TestNumbers.cpp
TestSourceHighlighter.cpp
TestStrings.cpp
)
@ -20,5 +21,6 @@ endforeach()
target_link_libraries(TestContentFilter PRIVATE LibURL)
target_link_libraries(TestFetchURL PRIVATE LibURL)
target_link_libraries(TestSourceHighlighter PRIVATE LibURL LibWebView)
add_subdirectory("test-web")

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <LibURL/URL.h>
#include <LibWebView/SourceHighlighter.h>
TEST_CASE(highlight_script_with_braces)
{
// Regression test for https://github.com/LadybirdBrowser/ladybird/issues/8529
auto source = "<script>\nfunction foo() {\n return 1;\n}\n</script>"_string;
URL::URL base_url {};
auto result = WebView::highlight_source({}, base_url, source, Syntax::Language::HTML, WebView::HighlightOutputMode::SourceOnly);
EXPECT(!result.is_empty());
}