diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-10-07 20:12:36 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-07 20:12:36 -0500 |
| commit | bc3aa9467ae1e2d0ea1727093af9b0af14965e69 (patch) | |
| tree | 8db3b735daed484507129eb0683db88ddec14210 /azalea-nbt/src | |
| parent | 695efef66fdf1e08f0cb6d8783c085875100fa2d (diff) | |
| download | azalea-drasl-bc3aa9467ae1e2d0ea1727093af9b0af14965e69.tar.xz | |
Replace impl Read with Cursor<&[u8]> (#26)
* Start getting rid of Cursor
* try to make the tests pass and fail
* make the tests pass
* remove unused uses
* fix clippy warnings
* fix potential OOM exploits
* fix OOM in az-nbt
* fix nbt benchmark
* fix a test
* start replacing it with Cursor<Vec<u8>>
* wip
* fix all the issues
* fix all tests
* fix nbt benchmark
* fix warnings
Diffstat (limited to 'azalea-nbt/src')
| -rwxr-xr-x | azalea-nbt/src/decode.rs | 56 | ||||
| -rwxr-xr-x | azalea-nbt/src/error.rs | 8 | ||||
| -rwxr-xr-x | azalea-nbt/src/lib.rs | 5 |
3 files changed, 46 insertions, 23 deletions
diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs index 2ab337fc..8a1dfab5 100755 --- a/azalea-nbt/src/decode.rs +++ b/azalea-nbt/src/decode.rs @@ -4,20 +4,31 @@ use ahash::AHashMap; use azalea_buf::{BufReadError, McBufReadable}; use byteorder::{ReadBytesExt, BE}; use flate2::read::{GzDecoder, ZlibDecoder}; +use std::io::Cursor; use std::io::{BufRead, Read}; #[inline] -fn read_string(stream: &mut impl Read) -> Result<String, Error> { - let length = stream.read_u16::<BE>()?; +fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], Error> { + if length > buf.get_ref().len() { + return Err(Error::UnexpectedEof); + } + let initial_position = buf.position() as usize; + buf.set_position(buf.position() + length as u64); + let data = &buf.get_ref()[initial_position..initial_position + length]; + Ok(data) +} - let mut buf = vec![0; length as usize]; - stream.read_exact(&mut buf)?; - Ok(String::from_utf8(buf)?) +#[inline] +fn read_string(stream: &mut Cursor<&[u8]>) -> Result<String, Error> { + let length = stream.read_u16::<BE>()? as usize; + + let buf = read_bytes(stream, length)?; + Ok(std::str::from_utf8(buf)?.to_string()) } impl Tag { #[inline] - fn read_known(stream: &mut impl Read, id: u8) -> Result<Tag, Error> { + fn read_known(stream: &mut Cursor<&[u8]>, id: u8) -> Result<Tag, Error> { Ok(match id { // Signifies the end of a TAG_Compound. It is only ever used inside // a TAG_Compound, and is not named despite being in a TAG_Compound @@ -39,9 +50,8 @@ impl Tag { // A length-prefixed array of signed bytes. The prefix is a signed // integer (thus 4 bytes) 7 => { - let length = stream.read_u32::<BE>()?; - let mut bytes = vec![0; length as usize]; - stream.read_exact(&mut bytes)?; + let length = stream.read_u32::<BE>()? as usize; + let bytes = read_bytes(stream, length)?.to_vec(); Tag::ByteArray(bytes) } // A length-prefixed modified UTF-8 string. The prefix is an @@ -58,8 +68,8 @@ impl Tag { // parsers should accept any type if the length is <= 0). 9 => { let type_id = stream.read_u8()?; - let length = stream.read_i32::<BE>()?; - let mut list = Vec::with_capacity(length as usize); + let length = stream.read_u32::<BE>()?; + let mut list = Vec::new(); for _ in 0..length { list.push(Tag::read_known(stream, type_id)?); } @@ -84,7 +94,10 @@ impl Tag { // signed integer (thus 4 bytes) and indicates the number of 4 byte // integers. 11 => { - let length = stream.read_u32::<BE>()?; + let length = stream.read_u32::<BE>()? as usize; + if length * 4 > stream.get_ref().len() { + return Err(Error::UnexpectedEof); + } let mut ints = Vec::with_capacity(length as usize); for _ in 0..length { ints.push(stream.read_i32::<BE>()?); @@ -94,7 +107,10 @@ impl Tag { // A length-prefixed array of signed longs. The prefix is a signed // integer (thus 4 bytes) and indicates the number of 8 byte longs. 12 => { - let length = stream.read_u32::<BE>()?; + let length = stream.read_u32::<BE>()? as usize; + if length * 8 > stream.get_ref().len() { + return Err(Error::UnexpectedEof); + } let mut longs = Vec::with_capacity(length as usize); for _ in 0..length { longs.push(stream.read_i64::<BE>()?); @@ -105,7 +121,7 @@ impl Tag { }) } - pub fn read(stream: &mut impl Read) -> Result<Tag, Error> { + pub fn read(stream: &mut Cursor<&[u8]>) -> Result<Tag, Error> { // default to compound tag // the parent compound only ever has one item @@ -123,17 +139,21 @@ impl Tag { pub fn read_zlib(stream: &mut impl BufRead) -> Result<Tag, Error> { let mut gz = ZlibDecoder::new(stream); - Tag::read(&mut gz) + let mut buf = Vec::new(); + gz.read_to_end(&mut buf)?; + Tag::read(&mut Cursor::new(&buf)) } - pub fn read_gzip(stream: &mut impl Read) -> Result<Tag, Error> { + pub fn read_gzip(stream: &mut Cursor<Vec<u8>>) -> Result<Tag, Error> { let mut gz = GzDecoder::new(stream); - Tag::read(&mut gz) + let mut buf = Vec::new(); + gz.read_to_end(&mut buf)?; + Tag::read(&mut Cursor::new(&buf)) } } impl McBufReadable for Tag { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(Tag::read(buf)?) } } diff --git a/azalea-nbt/src/error.rs b/azalea-nbt/src/error.rs index ef4a9e9f..308c74c8 100755 --- a/azalea-nbt/src/error.rs +++ b/azalea-nbt/src/error.rs @@ -3,7 +3,8 @@ pub enum Error { InvalidTagType(u8), InvalidTag, WriteError(std::io::Error), - Utf8Error(std::string::FromUtf8Error), + Utf8Error(std::str::Utf8Error), + UnexpectedEof, } impl std::fmt::Display for Error { @@ -13,6 +14,7 @@ impl std::fmt::Display for Error { Error::InvalidTag => write!(f, "Invalid tag"), Error::WriteError(e) => write!(f, "Write error: {}", e), Error::Utf8Error(e) => write!(f, "Utf8 error: {}", e), + Error::UnexpectedEof => write!(f, "Unexpected EOF"), } } } @@ -22,8 +24,8 @@ impl From<std::io::Error> for Error { Error::WriteError(e) } } -impl From<std::string::FromUtf8Error> for Error { - fn from(e: std::string::FromUtf8Error) -> Self { +impl From<std::str::Utf8Error> for Error { + fn from(e: std::str::Utf8Error) -> Self { Error::Utf8Error(e) } } diff --git a/azalea-nbt/src/lib.rs b/azalea-nbt/src/lib.rs index c644cfdc..e20049e0 100755 --- a/azalea-nbt/src/lib.rs +++ b/azalea-nbt/src/lib.rs @@ -8,10 +8,11 @@ pub use tag::Tag; #[cfg(test)] mod tests { + use std::io::Cursor; + use super::*; use ahash::AHashMap; use azalea_buf::{McBufReadable, McBufWritable}; - use std::io::Cursor; #[test] fn mcbuf_nbt() { @@ -25,7 +26,7 @@ mod tests { )])); tag.write_into(&mut buf).unwrap(); - let mut buf = Cursor::new(buf); + let mut buf = Cursor::new(&buf[..]); let result = Tag::read_from(&mut buf).unwrap(); assert_eq!( |
