Add lexer regression tests to the parser crate - #132
Merged
Conversation
These tests prepare for an upgrade of the logos crate. The lexer gets untrusted input. A change in logos behavior can cause incorrect tokens, incorrect spans, out-of-bounds data access, or a denial of service. These tests pin the current behavior and make regressions visible. This change adds tests only. It does not change production code. Unit tests in src/lexer/logos_lexer.rs: - Test all punctuators, variable names, and ignored tokens, with exact spans. - Test edge cases in strings, block strings, and numbers. - Compare the full token stream for a document with all token types. - Test the LogosLexer iterator, the token count, and the max tokens limit. Safety tests in src/lexer/logos_lexer/safety_tests.rs: - Lex a corpus of hostile inputs. Assert that the lexer terminates, makes progress, consumes the full input, and returns spans that are in bounds and on char boundaries. - Lex each prefix and each suffix of a document to simulate unexpected end of input in each lexer state. - Lex large hostile inputs that must complete in linear-like time. - Pin the current stack usage for long numeric tokens and long runs of ignored characters. Integration tests in tests/lexer_adversarial_test.rs: - Parse hostile documents through the public API and convert the errors, which slices the source by span. - Show that the max tokens limit bounds the work for large documents. Known issue: with logos 0.15, the matchers for numeric tokens and for runs of ignored characters use stack space proportional to the run length in unoptimized builds. One numeric token with approximately 5,000 or more digits causes a stack overflow in unoptimized builds. Two ignored tests document this issue. Run `cargo test -p bluejay-parser -- --ignored` in a debug build after each logos upgrade. If the tests pass, remove the ignore attributes. Assisted-By: devx/a4890344-dddf-4733-a94e-71230a3953d1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
We will upgrade the
logoscrate soon. The lexer gets untrusted input. A change inlogosbehavior can cause incorrect tokens, incorrect spans, out-of-bounds data access, or a denial of service. These tests pin the current behavior and make regressions visible.This change adds tests only. It does not change production code.
What
Unit tests in
src/lexer/logos_lexer.rs:remainder()andbump(). These logos APIs are the most likely place for subtle changes between versions.LogosLexeriterator, the token count, and the max tokens limit.Safety tests in
src/lexer/logos_lexer/safety_tests.rs:charboundaries. Spans with incorrect bounds can cause panics in error formatting, which slices the source by span.Integration tests in
tests/lexer_adversarial_test.rs:Known issue found while writing these tests
With logos 0.15, the generated matchers for numeric tokens and for runs of ignored characters use stack space proportional to the run length in unoptimized builds. Optimized builds compile the recursion into loops and are not affected. As a result of this, one numeric token with approximately 5,000 or more digits, or one run of approximately 50,000 or more ignored characters, causes a stack overflow in unoptimized builds. The max tokens limit does not protect against this, because each input is a single token.
Two tests document this issue. They are marked with
#[ignore]because a failure aborts the test process. After each logos upgrade, run this command in a debug build:If the tests pass, remove the
#[ignore]attributes.How to verify