1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 07:26:04 +00:00

fix memory leak on error

This commit is contained in:
mat 2024-05-12 21:01:29 +00:00
parent 4aa3effbf1
commit 33366ff085
4 changed files with 43 additions and 13 deletions

View file

@ -50,10 +50,11 @@ fn bench_file(filename: &str, c: &mut Criterion) {
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
fn bench(c: &mut Criterion) {
// bench_file("bigtest.nbt", c);
// bench_file("simple_player.dat", c);
bench_file("bigtest.nbt", c);
bench_file("simple_player.dat", c);
bench_file("complex_player.dat", c);
// bench_file("level.dat", c);
bench_file("level.dat", c);
// bench_file("stringtest.nbt", c);
// bench_file("inttest16.nbt", c);

View file

@ -35,7 +35,7 @@ impl<'a> NbtCompound<'a> {
return Err(Error::MaxDepthExceeded);
}
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
let alloc_mut = unsafe { alloc.get().as_mut().unwrap_unchecked() };
let mut tags = alloc_mut.start_named_tags(depth);
loop {
@ -43,14 +43,26 @@ impl<'a> NbtCompound<'a> {
if tag_type == END_ID {
break;
}
let tag_name = read_string(data)?;
tags.push((
tag_name,
NbtTag::read_with_type(data, alloc, tag_type, depth)?,
));
let tag_name = match read_string(data) {
Ok(name) => name,
Err(_) => {
alloc_mut.finish_named_tags(tags, depth);
// the only error read_string can return is UnexpectedEof, so this makes it
// slightly faster
return Err(Error::UnexpectedEof);
}
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
};
let tag = match NbtTag::read_with_type(data, alloc, tag_type, depth) {
Ok(tag) => tag,
Err(e) => {
alloc_mut.finish_named_tags(tags, depth);
return Err(e);
}
};
tags.push((tag_name, tag));
}
let alloc_mut = unsafe { alloc.get().as_mut().unwrap_unchecked() };
let values = alloc_mut.finish_named_tags(tags, depth);
Ok(Self { values })

View file

@ -80,7 +80,14 @@ impl<'a> NbtList<'a> {
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
let mut tags = alloc_mut.start_unnamed_list_tags(depth);
for _ in 0..length {
tags.push(NbtList::read(data, alloc, depth + 1)?)
let tag = match NbtList::read(data, alloc, depth + 1) {
Ok(tag) => tag,
Err(e) => {
alloc_mut.finish_unnamed_list_tags(tags, depth);
return Err(e);
}
};
tags.push(tag)
}
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
alloc_mut.finish_unnamed_list_tags(tags, depth)
@ -92,7 +99,14 @@ impl<'a> NbtList<'a> {
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
let mut tags = alloc_mut.start_unnamed_compound_tags(depth);
for _ in 0..length {
tags.push(NbtCompound::read_with_depth(data, alloc, depth + 1)?)
let tag = match NbtCompound::read_with_depth(data, alloc, depth + 1) {
Ok(tag) => tag,
Err(e) => {
alloc_mut.finish_unnamed_compound_tags(tags, depth);
return Err(e);
}
};
tags.push(tag);
}
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
alloc_mut.finish_unnamed_compound_tags(tags, depth)

View file

@ -261,6 +261,7 @@ pub struct ContiguousTagsAllocator<T> {
}
impl<T> ContiguousTagsAllocator<T> {
#[inline(never)]
fn grow(&mut self) {
let new_cap = if self.is_new_allocation {
// this makes sure we don't allocate 0 bytes
@ -297,6 +298,7 @@ impl<T> ContiguousTagsAllocator<T> {
self.alloc.len = self.size;
}
#[inline]
pub fn push(&mut self, value: T) {
// check if we need to reallocate
if self.alloc.len == self.alloc.cap {
@ -305,7 +307,8 @@ impl<T> ContiguousTagsAllocator<T> {
// push the new tag
unsafe {
std::ptr::write(self.alloc.ptr.as_ptr().add(self.alloc.len), value);
let end = self.alloc.ptr.as_ptr().add(self.alloc.len);
std::ptr::write(end, value);
}
self.alloc.len += 1;
self.size += 1;