Skip to content
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

Remove usage of smallvec #40

Closed
wants to merge 1 commit into from
Closed

Conversation

jbg
Copy link

@jbg jbg commented Sep 19, 2019

Due to safety concerns, we are trying to eliminate use of smallvec from our dependencies, starting with the ones in critical paths handling user input.

smallvec contains a large amount of unsafe, probably contains UB that just happens to currently be working correctly, and has been the source of several security vulnerabilities in the past. For us, the use of this library in the context of unicode normalisation (which in our application is operating on user input) presents an unacceptable level of risk.

There is a performance regression from this change, which is acceptable in our application but may not be in others. If this performance regression is considered an unacceptable tradeoff for safety, then perhaps a feature could be used to enable/disable smallvec usage?

without smallvec:

running 22 tests
test bench_is_nfc_ascii                      ... bench:          17 ns/iter (+/- 2)
test bench_is_nfc_normalized                 ... bench:          29 ns/iter (+/- 3)
test bench_is_nfc_not_normalized             ... bench:         612 ns/iter (+/- 75)
test bench_is_nfc_stream_safe_ascii          ... bench:          17 ns/iter (+/- 2)
test bench_is_nfc_stream_safe_normalized     ... bench:          39 ns/iter (+/- 4)
test bench_is_nfc_stream_safe_not_normalized ... bench:         663 ns/iter (+/- 69)
test bench_is_nfd_ascii                      ... bench:          16 ns/iter (+/- 2)
test bench_is_nfd_normalized                 ... bench:          39 ns/iter (+/- 4)
test bench_is_nfd_not_normalized             ... bench:          15 ns/iter (+/- 1)
test bench_is_nfd_stream_safe_ascii          ... bench:          16 ns/iter (+/- 1)
test bench_is_nfd_stream_safe_normalized     ... bench:          49 ns/iter (+/- 6)
test bench_is_nfd_stream_safe_not_normalized ... bench:          15 ns/iter (+/- 1)
test bench_nfc_ascii                         ... bench:         612 ns/iter (+/- 67)
test bench_nfc_long                          ... bench:     190,220 ns/iter (+/- 47,039)
test bench_nfd_ascii                         ... bench:         414 ns/iter (+/- 78)
test bench_nfd_long                          ... bench:     130,626 ns/iter (+/- 19,313)
test bench_nfkc_ascii                        ... bench:         621 ns/iter (+/- 114)
test bench_nfkc_long                         ... bench:     206,319 ns/iter (+/- 11,866)
test bench_nfkd_ascii                        ... bench:         422 ns/iter (+/- 66)
test bench_nfkd_long                         ... bench:     142,023 ns/iter (+/- 12,416)
test bench_streamsafe_adversarial            ... bench:         391 ns/iter (+/- 30)
test bench_streamsafe_ascii                  ... bench:          74 ns/iter (+/- 9)

test result: ok. 0 passed; 0 failed; 0 ignored; 22 measured; 0 filtered out



with smallvec:

running 22 tests
test bench_is_nfc_ascii                      ... bench:          17 ns/iter (+/- 3)
test bench_is_nfc_normalized                 ... bench:          29 ns/iter (+/- 2)
test bench_is_nfc_not_normalized             ... bench:         348 ns/iter (+/- 46)
test bench_is_nfc_stream_safe_ascii          ... bench:          17 ns/iter (+/- 4)
test bench_is_nfc_stream_safe_normalized     ... bench:          39 ns/iter (+/- 3)
test bench_is_nfc_stream_safe_not_normalized ... bench:         393 ns/iter (+/- 39)
test bench_is_nfd_ascii                      ... bench:          16 ns/iter (+/- 1)
test bench_is_nfd_normalized                 ... bench:          40 ns/iter (+/- 8)
test bench_is_nfd_not_normalized             ... bench:          15 ns/iter (+/- 1)
test bench_is_nfd_stream_safe_ascii          ... bench:          16 ns/iter (+/- 2)
test bench_is_nfd_stream_safe_normalized     ... bench:          50 ns/iter (+/- 8)
test bench_is_nfd_stream_safe_not_normalized ... bench:          15 ns/iter (+/- 1)
test bench_nfc_ascii                         ... bench:         499 ns/iter (+/- 32)
test bench_nfc_long                          ... bench:     185,101 ns/iter (+/- 24,584)
test bench_nfd_ascii                         ... bench:         260 ns/iter (+/- 35)
test bench_nfd_long                          ... bench:     110,856 ns/iter (+/- 15,114)
test bench_nfkc_ascii                        ... bench:         493 ns/iter (+/- 82)
test bench_nfkc_long                         ... bench:     201,455 ns/iter (+/- 34,208)
test bench_nfkd_ascii                        ... bench:         284 ns/iter (+/- 67)
test bench_nfkd_long                         ... bench:     128,826 ns/iter (+/- 23,951)
test bench_streamsafe_adversarial            ... bench:         409 ns/iter (+/- 98)
test bench_streamsafe_ascii                  ... bench:          77 ns/iter (+/- 12)

test result: ok. 0 passed; 0 failed; 0 ignored; 22 measured; 0 filtered out

@Manishearth
Copy link
Member

Yeah SmallVec is used specifically for its perf benefit here. Note that none of those CVEs affect this crate, which uses relatively simple APIs.

We should audit the crate further and try to run it with miri, but we aren't going to remove it.

Folks may be okay with a feature flag.

@Shnatsel
Copy link
Contributor

For posterity, #54 has replaced use of SmallVec with safe code without regressing performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants