deno_lint icon indicating copy to clipboard operation
deno_lint copied to clipboard

UB in js_regex::Reader due to constructing invalid char

Open saethlin opened this issue 2 years ago • 0 comments

Hi, I run Miri on a lot of published crates to look for UB. It looks to me like there is a bug related to this code: https://github.com/denoland/deno_lint/blob/dfe78729850680b68e1659c64ea69bdee447e38c/src/js_regex/reader.rs#L125-L129

To reproduce, you can run

MIRIFLAGS=-Zmiri-disable-stacked-borrows cargo +nightly miri test

and you should eventually see this, plus a backtrace:

test js_regex::reader::tests::at_test_es_compliance ... error: Undefined Behavior: type validation failed: encountered 0x0000dbc0, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

Note that you do need to disable stacked borrows checking to get to this test, there's probably aliasing problems elsewhere in this codebase.

The standard library also has a debug assertion for misuse of char::from_u32_unchecked which can detect this. All standard library debug assertions are compiled out by default though, so you'll need to run something like this:

cargo +nightly test -Zbuild-std --target=x86_64-unknown-linux-gnu

and you should see something like this:

failures:

---- js_regex::reader::tests::at_test_es_compliance stdout ----
thread 'js_regex::reader::tests::at_test_es_compliance' panicked at 'called `Option::unwrap()` on a `None` value', /home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/char/convert.rs:26:51
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- js_regex::tests::basic_invalid stdout ----
thread 'js_regex::tests::basic_invalid' panicked at 'called `Option::unwrap()` on a `None` value', /home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/char/convert.rs:26:51

---- js_regex::tests::basic_valid stdout ----
thread 'js_regex::tests::basic_valid' panicked at 'called `Option::unwrap()` on a `None` value', /home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/char/convert.rs:26:51

---- js_regex::tests::basic_invalid_2015 stdout ----
thread 'js_regex::tests::basic_invalid_2015' panicked at 'called `Option::unwrap()` on a `None` value', /home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/char/convert.rs:26:51

---- js_regex::tests::unicode_group_names_invalid_2020 stdout ----
thread 'js_regex::tests::unicode_group_names_invalid_2020' panicked at 'called `Option::unwrap()` on a `None` value', /home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/char/convert.rs:26:51


failures:
    js_regex::reader::tests::at_test_es_compliance
    js_regex::tests::basic_invalid
    js_regex::tests::basic_invalid_2015
    js_regex::tests::basic_valid
    js_regex::tests::unicode_group_names_invalid_2020

test result: FAILED. 302 passed; 5 failed; 9 ignored; 0 measured; 0 filtered out; finished in 0.17s

error: test failed, to rerun pass '--lib'

Ah, this bug actually originates in the js-regex crate which seems to have been copy-pasted into this crate with https://github.com/denoland/deno_lint/pull/252

saethlin avatar May 28 '22 20:05 saethlin