1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 15:36:03 +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; static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
fn bench(c: &mut Criterion) { fn bench(c: &mut Criterion) {
// bench_file("bigtest.nbt", c); bench_file("bigtest.nbt", c);
// bench_file("simple_player.dat", c); bench_file("simple_player.dat", c);
bench_file("complex_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("stringtest.nbt", c);
// bench_file("inttest16.nbt", c); // bench_file("inttest16.nbt", c);

View file

@ -35,7 +35,7 @@ impl<'a> NbtCompound<'a> {
return Err(Error::MaxDepthExceeded); 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); let mut tags = alloc_mut.start_named_tags(depth);
loop { loop {
@ -43,14 +43,26 @@ impl<'a> NbtCompound<'a> {
if tag_type == END_ID { if tag_type == END_ID {
break; break;
} }
let tag_name = read_string(data)?;
tags.push(( let tag_name = match read_string(data) {
tag_name, Ok(name) => name,
NbtTag::read_with_type(data, alloc, tag_type, depth)?, 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 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() }; let alloc_mut = unsafe { alloc.get().as_mut().unwrap_unchecked() };
let values = alloc_mut.finish_named_tags(tags, depth); let values = alloc_mut.finish_named_tags(tags, depth);
Ok(Self { values }) Ok(Self { values })

View file

@ -80,7 +80,14 @@ impl<'a> NbtList<'a> {
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() }; let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
let mut tags = alloc_mut.start_unnamed_list_tags(depth); let mut tags = alloc_mut.start_unnamed_list_tags(depth);
for _ in 0..length { 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() }; let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
alloc_mut.finish_unnamed_list_tags(tags, depth) 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 alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
let mut tags = alloc_mut.start_unnamed_compound_tags(depth); let mut tags = alloc_mut.start_unnamed_compound_tags(depth);
for _ in 0..length { 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() }; let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
alloc_mut.finish_unnamed_compound_tags(tags, depth) alloc_mut.finish_unnamed_compound_tags(tags, depth)

View file

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