-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[BUG] Unsoundness in Bytes::read()
#102
Labels
bug
Something isn't working
Comments
One potential patch for this is the following, since the callers do uphold this invariant. Safety docs would also need to be updated. A better way to do this is to either use some POD trait (I don't recall if there's one in use in Patchdiff --git a/lexical-parse-float/src/slow.rs b/lexical-parse-float/src/slow.rs
index 26a0d90..8891bba 100644
--- a/lexical-parse-float/src/slow.rs
+++ b/lexical-parse-float/src/slow.rs
@@ -335,7 +335,7 @@ macro_rules! round_up_nonzero {
// First try reading 8-digits at a time.
if iter.is_contiguous() {
- while let Some(value) = iter.read::<u64>() {
+ while let Some(value) = unsafe { iter.read::<u64>() } {
// SAFETY: safe since we have at least 8 bytes in the buffer.
unsafe { iter.step_by_unchecked(8) };
if value != 0x3030_3030_3030_3030 {
diff --git a/lexical-parse-integer/src/algorithm.rs b/lexical-parse-integer/src/algorithm.rs
index 3caedc6..bcc66a0 100644
--- a/lexical-parse-integer/src/algorithm.rs
+++ b/lexical-parse-integer/src/algorithm.rs
@@ -217,7 +217,7 @@ where
debug_assert!(Iter::IS_CONTIGUOUS);
// Read our digits, validate the input, and check from there.
- let bytes = u32::from_le(iter.read::<u32>()?);
+ let bytes = unsafe { u32::from_le(iter.read::<u32>()?) };
if is_4digits::<FORMAT>(bytes) {
// SAFETY: safe since we have at least 4 bytes in the buffer.
unsafe { iter.step_by_unchecked(4) };
@@ -289,7 +289,7 @@ where
debug_assert!(Iter::IS_CONTIGUOUS);
// Read our digits, validate the input, and check from there.
- let bytes = u64::from_le(iter.read::<u64>()?);
+ let bytes = unsafe { u64::from_le(iter.read::<u64>()?) };
if is_8digits::<FORMAT>(bytes) {
// SAFETY: safe since we have at least 8 bytes in the buffer.
unsafe { iter.step_by_unchecked(8) };
diff --git a/lexical-util/src/iterator.rs b/lexical-util/src/iterator.rs
index bb5f86d..18c760c 100644
--- a/lexical-util/src/iterator.rs
+++ b/lexical-util/src/iterator.rs
@@ -122,7 +122,7 @@ pub trait BytesIter<'a>: Iterator<Item = &'a u8> {
/// Try to read a value of a different type from the iterator.
/// This advances the internal state of the iterator.
- fn read<V>(&self) -> Option<V>;
+ unsafe fn read<V>(&self) -> Option<V>;
/// Advance the internal slice by `N` elements.
///
diff --git a/lexical-util/src/noskip.rs b/lexical-util/src/noskip.rs
index 22c511b..9df4cfb 100644
--- a/lexical-util/src/noskip.rs
+++ b/lexical-util/src/noskip.rs
@@ -120,7 +120,7 @@ impl<'a, const __: u128> Bytes<'a, __> {
/// Try to read a value of a different type from the iterator.
/// This advances the internal state of the iterator.
#[inline]
- pub fn read<V>(&self) -> Option<V> {
+ unsafe fn read<V>(&self) -> Option<V> {
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<V>() {
// SAFETY: safe since we've guaranteed the buffer is greater than
// the number of elements read.
@@ -288,7 +288,7 @@ impl<'a: 'b, 'b, const __: u128> BytesIter<'a> for BytesIterator<'a, 'b, __> {
}
#[inline]
- fn read<V>(&self) -> Option<V> {
+ unsafe fn read<V>(&self) -> Option<V> {
self.byte.read()
}
diff --git a/lexical-util/src/skip.rs b/lexical-util/src/skip.rs
index 4daaaa9..55e098f 100644
--- a/lexical-util/src/skip.rs
+++ b/lexical-util/src/skip.rs
@@ -442,7 +442,7 @@ impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> {
/// Try to read a value of a different type from the iterator.
/// This advances the internal state of the iterator.
#[inline]
- pub fn read<V>(&self) -> Option<V> {
+ unsafe fn read<V>(&self) -> Option<V> {
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<V>() {
// SAFETY: safe since we've guaranteed the buffer is greater than
// the number of elements read. |
This was referenced Sep 9, 2024
This was referenced Sep 16, 2024
This was referenced Sep 26, 2024
This was referenced Nov 11, 2024
# for free
to join this conversation on GitHub.
Already have an account?
# to comment
Description
Bytes::read()
only requires thatV
be of the right length, and imposes no validity requirements. This is trivially usable to create unsoundness.Test case
Prerequisites
rustc 1.68.0 (2c8cc3432 2023-03-06)
lexical_util
0.8.5parsing
The text was updated successfully, but these errors were encountered: