-
-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Lexer::clone
leak and UB + tests
#390
Conversation
`Lexer::clone` shouldn't clone the inner `ManuallyDrop`, because doing so clones the inner value, which is moved out in `Lexer::next`. This causes use-after-free if the lexer is cloned after the last-returned token is dropped, especially if the token contains an overridden implementation of `Clone` (such as `Rc`) that tries to read the dropped data. It causes a memory leak if the token contains a heap-allocated value, because cloning makes a new allocation. This allocation is in the `ManuallyDrop` and it's guaranteed to be overridden before the call to `ManuallyDrop::take`, so it's never freed. Another thing: maciejhirsz#263 (make `Lexer` implement `Copy`) probably should be added (referencing here because it looks like the issue has been forgotten).
Hello @Jakobeha, thank you for this very comprehensive analysis! But, if I understand well, then cloning |
Cloning can be used as a kind of lookahead: the cloned lexer will return the exact same tokens that would be returned by the original lexer without advancing the original (provided the lexing functions are pure). One can also I'm not sure if it's the most efficient way to implement a lookahead (I don't know the performance vs storing an array of spans and tokens and then making The same thing (creating a "lookahead" lexer) can also be done using let mut clone = Lexer::with_extras(original.source(), original.extras);
clone.bump(original.span().end); Though it's less convenient, especially if the lexer is wrapped in another data structure, because then Related, I also thought about |
This is a pretty good catch! FWIW whenever the mythical rewrite happens that turns all the internal gotos from functions to |
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [logos](https://logos.maciej.codes/) ([source](https://togithub.com/maciejhirsz/logos)) | dependencies | patch | `0.14.0` -> `0.14.1` | --- ### Release Notes <details> <summary>maciejhirsz/logos (logos)</summary> ### [`v0.14.1`](https://togithub.com/maciejhirsz/logos/releases/tag/v0.14.1): 0.14.1 - Debug feature and fixes #### What's Changed - fix(doc): reset logos2 to logos by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/372](https://togithub.com/maciejhirsz/logos/pull/372) - chore(book): add JSON-borrowed parser example by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/373](https://togithub.com/maciejhirsz/logos/pull/373) - Add Rc<T> and Arc<T> sources by [@​InfiniteCoder01](https://togithub.com/InfiniteCoder01) in [https://github.com/maciejhirsz/logos/pull/340](https://togithub.com/maciejhirsz/logos/pull/340) - Fix unicode dot by [@​RustyYato](https://togithub.com/RustyYato) in [https://github.com/maciejhirsz/logos/pull/376](https://togithub.com/maciejhirsz/logos/pull/376) - chore(docs): cleanup examples by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/381](https://togithub.com/maciejhirsz/logos/pull/381) - chore(lib): add debug feature by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/382](https://togithub.com/maciejhirsz/logos/pull/382) - Cleanup unused Source features by [@​kmicklas](https://togithub.com/kmicklas) in [https://github.com/maciejhirsz/logos/pull/335](https://togithub.com/maciejhirsz/logos/pull/335) - chore(deps): bump peaceiris/actions-mdbook from 1 to 2 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/maciejhirsz/logos/pull/387](https://togithub.com/maciejhirsz/logos/pull/387) - Fix `Lexer::clone` leak and UB + tests by [@​Jakobeha](https://togithub.com/Jakobeha) in [https://github.com/maciejhirsz/logos/pull/390](https://togithub.com/maciejhirsz/logos/pull/390) - fix(lib): correctly handle miss for loop in loop by [@​lukas-code](https://togithub.com/lukas-code) in [https://github.com/maciejhirsz/logos/pull/393](https://togithub.com/maciejhirsz/logos/pull/393) - chore(lib): remove error branch from LUT if it is unreachable by [@​RustyYato](https://togithub.com/RustyYato) in [https://github.com/maciejhirsz/logos/pull/386](https://togithub.com/maciejhirsz/logos/pull/386) - fix(docs): typo by [@​joerivanruth](https://togithub.com/joerivanruth) in [https://github.com/maciejhirsz/logos/pull/396](https://togithub.com/maciejhirsz/logos/pull/396) - chore(docs): Adds graph debug documentation to book by [@​afreeland](https://togithub.com/afreeland) in [https://github.com/maciejhirsz/logos/pull/379](https://togithub.com/maciejhirsz/logos/pull/379) - chore: drop python linting frmo pre-commit-config by [@​LeoDog896](https://togithub.com/LeoDog896) in [https://github.com/maciejhirsz/logos/pull/403](https://togithub.com/maciejhirsz/logos/pull/403) - refactor: don't use deprecated max_value() method by [@​LeoDog896](https://togithub.com/LeoDog896) in [https://github.com/maciejhirsz/logos/pull/404](https://togithub.com/maciejhirsz/logos/pull/404) - chore(version): bump logos version to 0.14.1 by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/409](https://togithub.com/maciejhirsz/logos/pull/409) - fix(docs): change old 0.14.0 by [@​jeertmans](https://togithub.com/jeertmans) in [https://github.com/maciejhirsz/logos/pull/410](https://togithub.com/maciejhirsz/logos/pull/410) #### New Contributors - [@​InfiniteCoder01](https://togithub.com/InfiniteCoder01) made their first contribution in [https://github.com/maciejhirsz/logos/pull/340](https://togithub.com/maciejhirsz/logos/pull/340) - [@​RustyYato](https://togithub.com/RustyYato) made their first contribution in [https://github.com/maciejhirsz/logos/pull/376](https://togithub.com/maciejhirsz/logos/pull/376) - [@​Jakobeha](https://togithub.com/Jakobeha) made their first contribution in [https://github.com/maciejhirsz/logos/pull/390](https://togithub.com/maciejhirsz/logos/pull/390) - [@​lukas-code](https://togithub.com/lukas-code) made their first contribution in [https://github.com/maciejhirsz/logos/pull/393](https://togithub.com/maciejhirsz/logos/pull/393) - [@​joerivanruth](https://togithub.com/joerivanruth) made their first contribution in [https://github.com/maciejhirsz/logos/pull/396](https://togithub.com/maciejhirsz/logos/pull/396) - [@​afreeland](https://togithub.com/afreeland) made their first contribution in [https://github.com/maciejhirsz/logos/pull/379](https://togithub.com/maciejhirsz/logos/pull/379) - [@​LeoDog896](https://togithub.com/LeoDog896) made their first contribution in [https://github.com/maciejhirsz/logos/pull/403](https://togithub.com/maciejhirsz/logos/pull/403) **Full Changelog**: maciejhirsz/logos@v0.14...v0.14.1 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/akrantz01/antsi). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM3LjQ0MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Lexer::clone
shouldn't clone the innerManuallyDrop
, because doing so clones the inner value, which is moved out inLexer::next
.This causes use-after-free if the lexer is cloned after the last-returned token is dropped, especially if the token contains an overridden implementation of
Clone
(such asRc
) that tries to read the dropped data.It causes a memory leak if the token contains a heap-allocated value, because cloning makes a new allocation. This allocation is in the
ManuallyDrop
and it's guaranteed to be overridden before the call toManuallyDrop::take
, so it's never freed.Another thing: #263 (make
Lexer
implementCopy
) probably should be added (referencing here because it looks like the issue has been forgotten).