From a31413e72ae664a92fcd8f31cb9e665030fcd213 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 14:02:46 -0800 Subject: [PATCH 01/19] Replace all memory allocations with fallible allocations and swap the global allocator in runtests.rs with the tests' own --- Cargo.lock | 14 +- Cargo.toml | 2 +- src/lib.rs | 2 + src/lib/xmlparse.rs | 352 ++++++++++++++---------------------------- src/tests/runtests.rs | 158 +++++++++++-------- 5 files changed, 217 insertions(+), 311 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3910e0a..a3748e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,17 +1,17 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "alloc-wg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484f71e69fc01231c3d44f939440e2fbcc0935146bad4c44cec187337952e522" - [[package]] name = "bencher" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5" +[[package]] +name = "fallible_collections" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eebb7b73a13e9b813587dd134eabd7f7d11d9aec26ee493e4078b44662141ee" + [[package]] name = "libc" version = "0.2.66" @@ -51,8 +51,8 @@ dependencies = [ name = "rexpat" version = "0.0.0" dependencies = [ - "alloc-wg", "bencher", + "fallible_collections", "libc", "wchar", ] diff --git a/Cargo.toml b/Cargo.toml index acc0ae0..98e5f98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ harness = false [dependencies] libc = "0.2" -alloc-wg = "0.7" +fallible_collections = "0.1.0" wchar = { path = "deps/wchar", optional = true } bencher = "0.1" diff --git a/src/lib.rs b/src/lib.rs index bdaeebe..8ecfbb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ #![feature(main)] #![feature(const_in_array_repeat_expressions)] #![feature(ptr_wrapping_offset_from)] +#![feature(try_reserve)] +#![feature(alloc_layout_extra)] #[cfg(all(feature = "unicode_wchar_t", not(target_os = "windows")))] compile_error!("Feature \"unicode_wchar_t\" is only supported on windows"); diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 80c170f..d59efc4 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -115,18 +115,18 @@ pub use crate::stdlib::{ __suseconds_t, __time_t, __timezone_ptr_t, __uint64_t, fprintf, getrandom, gettimeofday, ssize_t, stderr, timezone, uint64_t, FILE, GRND_NONBLOCK, _IO_FILE, }; -use crate::stdlib::{__assert_fail, malloc, memcmp, memcpy, memmove, memset, read, realloc}; -use ::libc::{self, __errno_location, close, free, getenv, getpid, open, strcmp}; +use crate::stdlib::{__assert_fail, memcmp, memcpy, memmove, memset, read}; +use ::libc::{self, __errno_location, close, getenv, getpid, open, strcmp}; pub use ::libc::{timeval, EINTR, INT_MAX, O_RDONLY}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, intptr_t}; #[cfg(feature = "getrandom_syscall")] use libc::{SYS_getrandom, syscall}; -use alloc_wg::alloc::{AllocRef, BuildAllocRef, DeallocRef, NonZeroLayout, ReallocRef}; -use alloc_wg::boxed::Box; +use fallible_collections::FallibleBox; -use std::collections::{hash_map, HashMap}; -use std::ptr::{self, NonNull}; +use std::alloc::{self, Layout}; +use std::collections::HashMap; +use std::ptr; impl STRING_POOL { #[inline] @@ -258,8 +258,8 @@ pub enum EncodingType { pub enum OldEncoding { Global(&'static dyn XmlEncoding), - Init(ExpatBox), - Unknown(ExpatBox), + Init(Box), + Unknown(Box), Internal(&'static dyn XmlEncoding), } @@ -647,7 +647,6 @@ pub struct XML_ParserStruct { macro works. */ pub m_userData: *mut c_void, pub m_buffer: *mut c_char, - pub m_mem: XML_Memory_Handling_Suite, /* first character to be parsed */ pub m_bufferPtr: *const c_char, /* past last character to be parsed */ @@ -667,7 +666,7 @@ pub struct XML_ParserStruct { pub m_protocolEncodingName: *const XML_Char, pub m_ns: XML_Bool, pub m_ns_triplets: XML_Bool, - pub m_unknownEncoding: Option>, + pub m_unknownEncoding: Option>, pub m_unknownEncodingData: *mut c_void, pub m_unknownEncodingRelease: Option ()>, pub m_prologState: super::xmlrole::PROLOG_STATE, @@ -738,7 +737,6 @@ pub struct STRING_POOL { pub end: *const XML_Char, pub ptr: *mut XML_Char, pub start: *mut XML_Char, - pub mem: *const XML_Memory_Handling_Suite, } impl STRING_POOL { @@ -749,7 +747,6 @@ impl STRING_POOL { end: ptr::null(), ptr: ptr::null_mut(), start: ptr::null_mut(), - mem: ptr::null(), } } } @@ -853,19 +850,19 @@ impl HashKey { } macro_rules! hash_insert { - ($parser:expr, $map:expr, $key:expr, $et:ident) => {{ + ($map:expr, $key:expr, $et:ident) => {{ let __key = $key; - match $map.entry(HashKey::from(__key)) { - hash_map::Entry::Occupied(e) => e.into_mut().as_mut(), - hash_map::Entry::Vacant(e) => { + let __hk = HashKey::from(__key); + if !$map.contains_key(&__hk) { + if $map.try_reserve(1).is_ok() { let v = $et { name: __key, ..std::mem::zeroed() }; - let b = ExpatBox::try_new_in(v, (*$parser).m_mem); - match b { - Ok(b) => e.insert(b).as_mut(), - Err(_) => std::ptr::null_mut() + if let Ok(b) = Box::try_new(v) { + $map.insert(__hk.clone(), b); } } } + $map.get_mut(&__hk) + .map_or_else(std::ptr::null_mut, |x| x.as_mut()) }}; } @@ -879,10 +876,10 @@ macro_rules! hash_lookup { #[repr(C)] #[derive(Clone)] pub struct DTD { - pub generalEntities: HashMap>, - pub elementTypes: HashMap>, - pub attributeIds: HashMap>, - pub prefixes: HashMap>, + pub generalEntities: HashMap>, + pub elementTypes: HashMap>, + pub attributeIds: HashMap>, + pub prefixes: HashMap>, pub pool: STRING_POOL, pub entityValuePool: STRING_POOL, pub keepProcessing: XML_Bool, @@ -890,8 +887,8 @@ pub struct DTD { pub standalone: XML_Bool, pub paramEntityRead: XML_Bool, // `test_alloc_nested_entities` counts the allocations, - // so we need to use `ExpatBox` here to pass that test - pub paramEntities: HashMap>, + // so we need to use `Box` here to pass that test + pub paramEntities: HashMap>, pub defaultPrefix: PREFIX, pub in_eldecl: XML_Bool, pub scaffold: *mut CONTENT_SCAFFOLD, @@ -1078,87 +1075,33 @@ pub const EXPAND_SPARE: c_int = 24; pub const INIT_SCAFFOLD_ELEMENTS: c_int = 32; +fn malloc_layout(size: usize) -> Layout { + Layout::from_size_align(size, 1) + .expect("failed to create Layout") +} + +fn malloc_array_layout(n: usize) -> Layout { + Layout::array::(n as usize) + .expect("failed to create array Layout") +} + macro_rules! MALLOC { - ($parser:expr, $size:expr $(,)?) => { - (*$parser) - .m_mem - .malloc_fcn - .expect("non-null function pointer")($size) + ($size:expr $(,)?) => { + alloc::alloc(malloc_layout($size as usize)) as *mut c_void }; } macro_rules! REALLOC { - ($parser:path, $ptr:expr, $size:expr $(,)?) => { - (*$parser) - .m_mem - .realloc_fcn - .expect("non-null function pointer")($ptr, $size) + ($ptr:expr, $size:expr $(,)?) => { + alloc::realloc($ptr as *mut u8, malloc_layout($size as usize), $size as usize) as *mut c_void }; } macro_rules! FREE { - ($parser:expr, $ptr:expr $(,)?) => { - (*$parser) - .m_mem - .free_fcn - .expect("non-null function pointer")($ptr) + ($ptr:expr $(,)?) => { + // FIXME: get the actual layout somehow + alloc::dealloc($ptr as *mut u8, Layout::new::()) }; } -impl AllocRef for XML_Memory_Handling_Suite { - type Error = (); - - fn alloc(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { - let size = layout.size().get() as u64; - let ptr = unsafe { - self.malloc_fcn - .expect("non-null function pointer")(size) - }; - NonNull::new(ptr as *mut u8).ok_or(()) - } -} - -impl ReallocRef for XML_Memory_Handling_Suite { - unsafe fn realloc( - &mut self, - ptr: NonNull, - _old_layout: NonZeroLayout, - new_layout: NonZeroLayout - ) -> Result, Self::Error> { - let size = new_layout.size().get() as u64; - let new_ptr = self - .realloc_fcn - .expect("non-null function pointer")(ptr.as_ptr() as *mut _, size); - NonNull::new(new_ptr as *mut u8).ok_or(()) - } -} - -impl DeallocRef for XML_Memory_Handling_Suite { - type BuildAlloc = Self; - - fn get_build_alloc(&mut self) -> Self::BuildAlloc { - self.clone() - } - - unsafe fn dealloc(&mut self, ptr: NonNull, _layout: NonZeroLayout) { - self - .free_fcn - .expect("non-null function pointer")(ptr.as_ptr() as *mut _); - } -} - -impl BuildAllocRef for XML_Memory_Handling_Suite { - type Ref = Self; - - unsafe fn build_alloc_ref( - &mut self, - _ptr: NonNull, - _layout: Option, - ) -> Self::Ref { - self.clone() - } -} - -pub type ExpatBox = Box; - /* Constructs a new parser; encoding is the encoding specified by the external protocol or NULL if there is none specified. */ @@ -1432,7 +1375,9 @@ pub unsafe extern "C" fn XML_ParserCreate_MM( mut memsuite: Option<&XML_Memory_Handling_Suite>, mut nameSep: *const XML_Char, ) -> XML_Parser { - XML_ParserStruct::create(encodingName, memsuite, nameSep, NULL as *mut DTD) + // FIXME + assert!(memsuite.is_none()); + XML_ParserStruct::create(encodingName, nameSep, NULL as *mut DTD) } impl XML_ParserStruct { @@ -1440,7 +1385,6 @@ impl XML_ParserStruct { Self { m_userData: ptr::null_mut(), m_buffer: ptr::null_mut(), - m_mem: XML_Memory_Handling_Suite::default(), /* first character to be parsed */ m_bufferPtr: ptr::null(), /* past last character to be parsed */ @@ -1531,29 +1475,15 @@ impl XML_ParserStruct { unsafe fn create( mut encodingName: *const XML_Char, - mut memsuite: Option<&XML_Memory_Handling_Suite>, mut nameSep: *const XML_Char, mut dtd: *mut DTD, ) -> XML_Parser { let use_namespaces = !nameSep.is_null(); let mut parser = XML_ParserStruct::new(use_namespaces); - let memsuite = match memsuite { - Some(m) => *m, - None => XML_Memory_Handling_Suite { - malloc_fcn: Some(malloc), - realloc_fcn: Some(realloc), - free_fcn: Some(free), - }, - }; - - // NOTE: Parser must have memsuite assigned beforehand or else it cannot deallocate - // objects when ExpatBox::try_new_in fails - parser.m_mem = memsuite; - - let mut parser = match ExpatBox::try_new_in(parser, memsuite) { + let mut parser = match Box::try_new(parser) { Ok(p) => p, - Err(()) => return ptr::null_mut(), + Err(_) => return ptr::null_mut(), }; // TODO: Move initialization into XML_ParserStruct::new @@ -1561,7 +1491,6 @@ impl XML_ParserStruct { parser.m_bufferLim = NULL as *const c_char; parser.m_attsSize = INIT_ATTS_SIZE; parser.m_atts = MALLOC!( - parser, (parser.m_attsSize as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut super::xmltok::ATTRIBUTE; @@ -1569,7 +1498,6 @@ impl XML_ParserStruct { return ptr::null_mut(); } parser.m_dataBuf = MALLOC!( - parser, 1024u64.wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut XML_Char; if parser.m_dataBuf.is_null() { @@ -1579,7 +1507,7 @@ impl XML_ParserStruct { if !dtd.is_null() { parser.m_dtd = dtd } else { - parser.m_dtd = dtdCreate(&parser.m_mem); + parser.m_dtd = dtdCreate(); if parser.m_dtd.is_null() { return ptr::null_mut(); } @@ -1599,9 +1527,9 @@ impl XML_ParserStruct { parser.m_nsAttsPower = 0; parser.m_protocolEncodingName = NULL as *const XML_Char; - if let XML_ParserStruct {ref m_mem, ref mut m_tempPool, ref mut m_temp2Pool, ..} = &mut *parser { - m_tempPool.init(m_mem); - m_temp2Pool.init(m_mem); + if let XML_ParserStruct {ref mut m_tempPool, ref mut m_temp2Pool, ..} = &mut *parser { + m_tempPool.init(); + m_temp2Pool.init(); }; parser.init(encodingName); @@ -1617,14 +1545,14 @@ impl XML_ParserStruct { { parser.m_mismatch = NULL as *const XML_Char; } - ExpatBox::into_raw(parser) + Box::into_raw(parser) } unsafe fn init(&mut self, mut encodingName: *const XML_Char) { self.m_processor = Some(prologInitProcessor as Processor); super::xmlrole::XmlPrologStateInit(&mut self.m_prologState as *mut _); if !encodingName.is_null() { - self.m_protocolEncodingName = copyString(encodingName, &self.m_mem) + self.m_protocolEncodingName = copyString(encodingName) } self.m_curBase = NULL as *const XML_Char; self.m_initEncoding = InitEncoding::new(&mut self.m_encoding, ptr::null()); @@ -1729,10 +1657,10 @@ impl XML_ParserStruct { } self.m_tempPool.clear(); self.m_temp2Pool.clear(); - FREE!(self, self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName as *mut c_void); self.m_protocolEncodingName = NULL as *const XML_Char; self.init(encodingName); - dtdReset(self.m_dtd, &self.m_mem); + dtdReset(self.m_dtd); XML_TRUE } } @@ -1765,13 +1693,13 @@ impl XML_ParserStruct { } /* Get rid of any previous encoding name */ - FREE!(self, self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName as *mut c_void); if encodingName.is_null() { /* No new encoding name */ self.m_protocolEncodingName = NULL as *const XML_Char } else { /* Copy the new encoding name into allocated memory */ - self.m_protocolEncodingName = copyString(encodingName, &self.m_mem); + self.m_protocolEncodingName = copyString(encodingName); if self.m_protocolEncodingName.is_null() { return XML_STATUS_ERROR_0 as XML_Status; } @@ -1903,11 +1831,10 @@ pub unsafe extern "C" fn XML_ExternalEntityParserCreate( if (*parser).m_ns != 0 { let mut tmp: [XML_Char; 2] = [0; 2]; *tmp.as_mut_ptr() = (*parser).m_namespaceSeparator; - parser = XML_ParserStruct::create(encodingName, Some(&(*parser).m_mem), tmp.as_mut_ptr(), newDtd) + parser = XML_ParserStruct::create(encodingName, tmp.as_mut_ptr(), newDtd) } else { parser = XML_ParserStruct::create( encodingName, - Some(&(*parser).m_mem), NULL as *const XML_Char, newDtd, ) @@ -1953,7 +1880,7 @@ pub unsafe extern "C" fn XML_ExternalEntityParserCreate( (*parser).m_prologState.inEntityValue = oldInEntityValue; if !context.is_null() { /* XML_DTD */ - if dtdCopy(oldParser, (*parser).m_dtd, oldDtd, &(*parser).m_mem) == 0 + if dtdCopy((*parser).m_dtd, oldDtd) == 0 || (*parser).setContext(context) == 0 { XML_ParserFree(parser); @@ -1976,15 +1903,15 @@ pub unsafe extern "C" fn XML_ExternalEntityParserCreate( parser } -unsafe fn destroyBindings(mut bindings: *mut BINDING, mut parser: XML_Parser) { +unsafe fn destroyBindings(mut bindings: *mut BINDING) { loop { let mut b: *mut BINDING = bindings; if b.is_null() { break; } bindings = (*b).nextTagBinding; - FREE!(parser, (*b).uri as *mut c_void); - FREE!(parser, b as *mut c_void); + FREE!((*b).uri as *mut c_void); + FREE!(b as *mut c_void); } } @@ -2007,8 +1934,8 @@ impl Drop for XML_ParserStruct { } p = tagList; tagList = (*tagList).parent; - FREE!(self, (*p).buf as *mut c_void); - destroyBindings((*p).bindings, self); + FREE!((*p).buf as *mut c_void); + destroyBindings((*p).bindings); } /* free m_openInternalEntities and m_freeInternalEntities */ entityList = self.m_openInternalEntities; @@ -2023,13 +1950,13 @@ impl Drop for XML_ParserStruct { } openEntity = entityList; entityList = (*entityList).next; - FREE!(self, openEntity as *mut c_void); + FREE!(openEntity as *mut c_void); } - destroyBindings(self.m_freeBindingList, self); - destroyBindings(self.m_inheritedBindings, self); + destroyBindings(self.m_freeBindingList); + destroyBindings(self.m_inheritedBindings); self.m_tempPool.destroy(); self.m_temp2Pool.destroy(); - FREE!(self, self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName as *mut c_void); /* external parameter entity parsers share the DTD structure parser->m_dtd with the root parser, so we must not destroy it */ @@ -2038,14 +1965,13 @@ impl Drop for XML_ParserStruct { dtdDestroy( self.m_dtd, self.m_parentParser.is_null() as XML_Bool, - &self.m_mem, ); } - FREE!(self, self.m_atts as *mut c_void); - FREE!(self, self.m_groupConnector as *mut c_void); - FREE!(self, self.m_buffer as *mut c_void); - FREE!(self, self.m_dataBuf as *mut c_void); - FREE!(self, self.m_nsAtts as *mut c_void); + FREE!(self.m_atts as *mut c_void); + FREE!(self.m_groupConnector as *mut c_void); + FREE!(self.m_buffer as *mut c_void); + FREE!(self.m_dataBuf as *mut c_void); + FREE!(self.m_nsAtts as *mut c_void); if self.m_unknownEncodingRelease.is_some() { self.m_unknownEncodingRelease .expect("non-null function pointer")(self.m_unknownEncodingData); @@ -2059,7 +1985,7 @@ pub unsafe extern "C" fn XML_ParserFree(parser: XML_Parser) { if parser.is_null() { return; } - let _ = ExpatBox::from_raw_in(parser, (*parser).m_mem); + let _ = Box::from_raw(parser); } /* If this function is called, then the parser will be passed as the first argument to callbacks instead of userData. The userData will @@ -2862,7 +2788,7 @@ impl XML_ParserStruct { self.m_errorCode = XML_ERROR_NO_MEMORY; return NULL as *mut c_void; } - newBuf = MALLOC!(&self, bufferSize as size_t) as *mut c_char; + newBuf = MALLOC!(bufferSize as size_t) as *mut c_char; if newBuf.is_null() { self.m_errorCode = XML_ERROR_NO_MEMORY; return NULL as *mut c_void; @@ -2881,7 +2807,7 @@ impl XML_ParserStruct { 0 }) + keep as c_long) as c_ulong, ); - FREE!(self, self.m_buffer as *mut c_void); + FREE!(self.m_buffer as *mut c_void); self.m_buffer = newBuf; self.m_bufferEnd = self .m_buffer @@ -3213,7 +3139,7 @@ pub unsafe extern "C" fn XML_GetCurrentColumnNumber(mut parser: XML_Parser) -> X #[no_mangle] pub unsafe extern "C" fn XML_FreeContentModel(mut parser: XML_Parser, mut model: *mut XML_Content) { if !parser.is_null() { - FREE!(parser, model as *mut c_void); + FREE!(model as *mut c_void); }; } /* Exposing the memory handling functions used in Expat */ @@ -3222,7 +3148,7 @@ pub unsafe extern "C" fn XML_MemMalloc(mut parser: XML_Parser, mut size: size_t) if parser.is_null() { return NULL as *mut c_void; } - return MALLOC!(parser, size); + return MALLOC!(size); } #[no_mangle] pub unsafe extern "C" fn XML_MemRealloc( @@ -3233,12 +3159,12 @@ pub unsafe extern "C" fn XML_MemRealloc( if parser.is_null() { return NULL as *mut c_void; } - return REALLOC!(parser, ptr, size); + return REALLOC!(ptr, size); } #[no_mangle] pub unsafe extern "C" fn XML_MemFree(mut parser: XML_Parser, mut ptr: *mut c_void) { if !parser.is_null() { - FREE!(parser, ptr); + FREE!(ptr); }; } /* This can be called within a handler for a start element, end @@ -3462,7 +3388,7 @@ impl XML_ParserStruct { ) as c_int; if bufSize as c_long > (*tag).bufEnd.wrapping_offset_from((*tag).buf) as c_long { let mut temp: *mut c_char = - REALLOC!(self, (*tag).buf as *mut c_void, bufSize as size_t) as *mut c_char; + REALLOC!((*tag).buf as *mut c_void, bufSize as size_t) as *mut c_char; if temp.is_null() { return XML_FALSE; } @@ -3846,13 +3772,13 @@ impl XML_ParserStruct { tag = self.m_freeTagList; self.m_freeTagList = (*self.m_freeTagList).parent } else { - tag = MALLOC!(self, ::std::mem::size_of::() as c_ulong) as *mut TAG; + tag = MALLOC!(::std::mem::size_of::() as c_ulong) as *mut TAG; if tag.is_null() { return XML_ERROR_NO_MEMORY; } - (*tag).buf = MALLOC!(self, 32u64) as *mut c_char; + (*tag).buf = MALLOC!(32u64) as *mut c_char; if (*tag).buf.is_null() { - FREE!(self, tag as *mut c_void); + FREE!(tag as *mut c_void); return XML_ERROR_NO_MEMORY; } (*tag).bufEnd = (*tag).buf.offset(INIT_TAG_BUF_SIZE as isize) @@ -3888,7 +3814,7 @@ impl XML_ParserStruct { } else { bufSize = ((*tag).bufEnd.wrapping_offset_from((*tag).buf) as c_int) << 1; let mut temp: *mut c_char = - REALLOC!(self, (*tag).buf as *mut c_void, bufSize as size_t) + REALLOC!((*tag).buf as *mut c_void, bufSize as size_t) as *mut c_char; if temp.is_null() { return XML_ERROR_NO_MEMORY; @@ -4321,7 +4247,6 @@ impl XML_ParserStruct { return XML_ERROR_NO_MEMORY; } let elementType = hash_insert!( - self, &mut (*dtd).elementTypes, name, ELEMENT_TYPE @@ -4342,7 +4267,6 @@ impl XML_ParserStruct { let mut temp: *mut super::xmltok::ATTRIBUTE = 0 as *mut super::xmltok::ATTRIBUTE; self.m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; temp = REALLOC!( - self, self.m_atts as *mut c_void, (self.m_attsSize as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) @@ -4563,7 +4487,6 @@ impl XML_ParserStruct { } nsAttsSize = (1) << self.m_nsAttsPower as c_int; temp_0 = REALLOC!( - self, self.m_nsAtts as *mut c_void, (nsAttsSize as c_ulong).wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut NS_ATT; @@ -4917,7 +4840,6 @@ impl XML_ParserStruct { if n > (*binding).uriAlloc { let mut p: *mut TAG = 0 as *mut TAG; uri = MALLOC!( - self, ((n + 24) as c_ulong).wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut XML_Char; if uri.is_null() { @@ -4937,7 +4859,7 @@ impl XML_ParserStruct { } p = (*p).parent } - FREE!(self, (*binding).uri as *mut c_void); + FREE!((*binding).uri as *mut c_void); (*binding).uri = uri } /* if m_namespaceSeparator != '\0' then uri includes it already */ @@ -5109,7 +5031,6 @@ unsafe extern "C" fn addBinding( b = (*parser).m_freeBindingList; if len > (*b).uriAlloc { let mut temp: *mut XML_Char = REALLOC!( - parser, (*b).uri as *mut c_void, (::std::mem::size_of::() as c_ulong).wrapping_mul((len + 24) as c_ulong) ) as *mut XML_Char; @@ -5121,16 +5042,15 @@ unsafe extern "C" fn addBinding( } (*parser).m_freeBindingList = (*b).nextTagBinding } else { - b = MALLOC!(parser, ::std::mem::size_of::() as c_ulong) as *mut BINDING; + b = MALLOC!(::std::mem::size_of::() as c_ulong) as *mut BINDING; if b.is_null() { return XML_ERROR_NO_MEMORY; } (*b).uri = MALLOC!( - parser, (::std::mem::size_of::() as c_ulong).wrapping_mul((len + 24) as c_ulong) ) as *mut XML_Char; if (*b).uri.is_null() { - FREE!(parser, b as *mut c_void); + FREE!(b as *mut c_void); return XML_ERROR_NO_MEMORY; } (*b).uriAlloc = len + EXPAND_SPARE @@ -5657,7 +5577,7 @@ impl XML_ParserStruct { self.m_ns != 0 ); if initialized { - match ExpatBox::try_new_in(unknown_enc, self.m_mem) { + match Box::try_new(unknown_enc) { Err(_) => { if info.release.is_some() { info.release.expect("non-null function pointer")(info.data); @@ -6112,7 +6032,6 @@ impl XML_ParserStruct { /* XML_DTD */ self.m_useForeignDTD = XML_FALSE; self.m_declEntity = hash_insert!( - self, &mut (*dtd).paramEntities, externalSubsetName.as_ptr(), ENTITY @@ -6173,7 +6092,6 @@ impl XML_ParserStruct { && self.m_handlers.hasExternalEntityRef() { let mut entity = hash_insert!( - self, &mut (*dtd).paramEntities, externalSubsetName.as_ptr(), ENTITY @@ -6231,7 +6149,6 @@ impl XML_ParserStruct { (*dtd).hasParamEntityRefs = XML_TRUE; if self.m_paramEntityParsing != 0 && self.m_handlers.hasExternalEntityRef() { let mut entity_0 = hash_insert!( - self, &mut (*dtd).paramEntities, externalSubsetName.as_ptr(), ENTITY @@ -6349,7 +6266,6 @@ impl XML_ParserStruct { self.m_declAttributeIsCdata, self.m_declAttributeIsId, 0 as *const XML_Char, - self, ) == 0 { return XML_ERROR_NO_MEMORY; @@ -6427,7 +6343,6 @@ impl XML_ParserStruct { self.m_declAttributeIsCdata, XML_FALSE, attVal, - self, ) == 0 { return XML_ERROR_NO_MEMORY; @@ -6551,7 +6466,6 @@ impl XML_ParserStruct { /* XML_DTD */ if self.m_declEntity.is_null() { self.m_declEntity = hash_insert!( - self, &mut (*dtd).paramEntities, externalSubsetName.as_ptr(), ENTITY @@ -6630,7 +6544,6 @@ impl XML_ParserStruct { return XML_ERROR_NO_MEMORY; } self.m_declEntity = hash_insert!( - self, &mut (*dtd).generalEntities, name, ENTITY @@ -6671,7 +6584,6 @@ impl XML_ParserStruct { return XML_ERROR_NO_MEMORY; } self.m_declEntity = hash_insert!( - self, &mut (*dtd).paramEntities, name_0, ENTITY @@ -6812,7 +6724,6 @@ impl XML_ParserStruct { if self.m_groupSize != 0 { self.m_groupSize = self.m_groupSize.wrapping_mul(2u32); let new_connector: *mut c_char = REALLOC!( - self, self.m_groupConnector as *mut c_void, self.m_groupSize as size_t ) as *mut c_char; @@ -6823,7 +6734,6 @@ impl XML_ParserStruct { self.m_groupConnector = new_connector; if !(*dtd).scaffIndex.is_null() { let new_scaff_index: *mut c_int = REALLOC!( - self, (*dtd).scaffIndex as *mut c_void, (self.m_groupSize as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) @@ -6837,7 +6747,7 @@ impl XML_ParserStruct { } else { self.m_groupSize = 32u32; self.m_groupConnector = - MALLOC!(self, self.m_groupSize as size_t) as *mut c_char; + MALLOC!(self.m_groupSize as size_t) as *mut c_char; if self.m_groupConnector.is_null() { self.m_groupSize = 0u32; return XML_ERROR_NO_MEMORY; @@ -7071,7 +6981,7 @@ impl XML_ParserStruct { if (*dtd).in_eldecl != 0 { if self.m_handlers.hasElementDecl() { let mut content: *mut XML_Content = - MALLOC!(self, ::std::mem::size_of::() as c_ulong) + MALLOC!(::std::mem::size_of::() as c_ulong) as *mut XML_Content; if content.is_null() { return XML_ERROR_NO_MEMORY; @@ -7440,7 +7350,6 @@ impl XML_ParserStruct { self.m_freeInternalEntities = (*openEntity).next } else { openEntity = MALLOC!( - self, ::std::mem::size_of::() as c_ulong ) as *mut OPEN_INTERNAL_ENTITY; if openEntity.is_null() { @@ -8309,7 +8218,6 @@ unsafe extern "C" fn defineAttribute( mut isCdata: XML_Bool, mut isId: XML_Bool, mut value: *const XML_Char, - mut parser: XML_Parser, ) -> c_int { let mut att: *mut DEFAULT_ATTRIBUTE = 0 as *mut DEFAULT_ATTRIBUTE; if !value.is_null() || isId as c_int != 0 { @@ -8331,7 +8239,6 @@ unsafe extern "C" fn defineAttribute( if (*type_0).allocDefaultAtts == 0 { (*type_0).allocDefaultAtts = 8; (*type_0).defaultAtts = MALLOC!( - parser, ((*type_0).allocDefaultAtts as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut DEFAULT_ATTRIBUTE; @@ -8343,7 +8250,6 @@ unsafe extern "C" fn defineAttribute( let mut temp: *mut DEFAULT_ATTRIBUTE = 0 as *mut DEFAULT_ATTRIBUTE; let mut count: c_int = (*type_0).allocDefaultAtts * 2; temp = REALLOC!( - parser, (*type_0).defaultAtts as *mut c_void, (count as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) @@ -8410,7 +8316,6 @@ impl XML_ParserStruct { return 0i32; } let prefix = hash_insert!( - self, &mut (*dtd).prefixes, (*dtd).pool.start as KEY, PREFIX @@ -8459,7 +8364,6 @@ impl XML_ParserStruct { /* skip quotation mark - its storage will be re-used (like in name[-1]) */ name = name.offset(1); let id = hash_insert!( - self, &mut (*dtd).attributeIds, name as *mut XML_Char, ATTRIBUTE_ID @@ -8484,7 +8388,6 @@ impl XML_ParserStruct { (*id).prefix = &mut (*dtd).defaultPrefix } else { (*id).prefix = hash_insert!( - self, &mut (*dtd).prefixes, name.offset(6), PREFIX @@ -8529,7 +8432,6 @@ impl XML_ParserStruct { return NULL as *mut ATTRIBUTE_ID; } (*id).prefix = hash_insert!( - self, &mut (*dtd).prefixes, (*dtd).pool.start as KEY, PREFIX @@ -8817,7 +8719,6 @@ impl XML_ParserStruct { return XML_FALSE; } prefix = hash_insert!( - self, &mut (*dtd).prefixes, prefix_name as KEY, PREFIX @@ -8921,15 +8822,13 @@ unsafe extern "C" fn normalizePublicId(mut publicId: *mut XML_Char) { *p = '\u{0}' as XML_Char; } -unsafe extern "C" fn dtdCreate(mut ms: *const XML_Memory_Handling_Suite) -> *mut DTD { - let mut p: *mut DTD = (*ms).malloc_fcn.expect("non-null function pointer")( - ::std::mem::size_of::() as c_ulong, - ) as *mut DTD; +unsafe extern "C" fn dtdCreate() -> *mut DTD { + let mut p: *mut DTD = alloc::alloc(Layout::new::()) as *mut DTD; if p.is_null() { return p; } - (*p).pool.init(ms); - (*p).entityValuePool.init(ms); + (*p).pool.init(); + (*p).entityValuePool.init(); // FIXME: we're writing over uninitialized memory, use `MaybeUninit`??? std::ptr::write(&mut (*p).generalEntities, Default::default()); std::ptr::write(&mut (*p).elementTypes, Default::default()); @@ -8954,10 +8853,10 @@ unsafe extern "C" fn dtdCreate(mut ms: *const XML_Memory_Handling_Suite) -> *mut } /* do not call if m_parentParser != NULL */ -unsafe extern "C" fn dtdReset(mut p: *mut DTD, mut ms: *const XML_Memory_Handling_Suite) { +unsafe extern "C" fn dtdReset(mut p: *mut DTD) { for e in (*p).elementTypes.values_mut() { if (*e).allocDefaultAtts != 0 { - (*ms).free_fcn.expect("non-null function pointer")((*e).defaultAtts as *mut c_void); + FREE!((*e).defaultAtts); } } (*p).generalEntities.clear(); @@ -8972,9 +8871,9 @@ unsafe extern "C" fn dtdReset(mut p: *mut DTD, mut ms: *const XML_Memory_Handlin (*p).defaultPrefix.name = NULL as *const XML_Char; (*p).defaultPrefix.binding = NULL as *mut BINDING; (*p).in_eldecl = XML_FALSE; - (*ms).free_fcn.expect("non-null function pointer")((*p).scaffIndex as *mut c_void); + FREE!((*p).scaffIndex); (*p).scaffIndex = NULL as *mut c_int; - (*ms).free_fcn.expect("non-null function pointer")((*p).scaffold as *mut c_void); + FREE!((*p).scaffold); (*p).scaffold = NULL as *mut CONTENT_SCAFFOLD; (*p).scaffLevel = 0; (*p).scaffSize = 0u32; @@ -8988,11 +8887,10 @@ unsafe extern "C" fn dtdReset(mut p: *mut DTD, mut ms: *const XML_Memory_Handlin unsafe extern "C" fn dtdDestroy( mut p: *mut DTD, mut isDocEntity: XML_Bool, - mut ms: *const XML_Memory_Handling_Suite, ) { for e in (*p).elementTypes.values_mut() { if (*e).allocDefaultAtts != 0 { - (*ms).free_fcn.expect("non-null function pointer")((*e).defaultAtts as *mut c_void); + FREE!((*e).defaultAtts); } } std::ptr::drop_in_place(&mut (*p).generalEntities); @@ -9004,20 +8902,18 @@ unsafe extern "C" fn dtdDestroy( (*p).pool.destroy(); (*p).entityValuePool.destroy(); if isDocEntity != 0 { - (*ms).free_fcn.expect("non-null function pointer")((*p).scaffIndex as *mut c_void); - (*ms).free_fcn.expect("non-null function pointer")((*p).scaffold as *mut c_void); + FREE!((*p).scaffIndex); + FREE!((*p).scaffold); } - (*ms).free_fcn.expect("non-null function pointer")(p as *mut c_void); + alloc::dealloc(p as *mut u8, Layout::new::()); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. The new DTD has already been initialized. */ unsafe extern "C" fn dtdCopy( - mut oldParser: XML_Parser, mut newDtd: *mut DTD, mut oldDtd: *const DTD, - mut ms: *const XML_Memory_Handling_Suite, ) -> c_int { /* Copy the prefix table. */ for oldP in (*oldDtd).prefixes.values() { @@ -9027,7 +8923,6 @@ unsafe extern "C" fn dtdCopy( return 0i32; } if hash_insert!( - oldParser, &mut (*newDtd).prefixes, name, PREFIX @@ -9061,7 +8956,6 @@ unsafe extern "C" fn dtdCopy( } name_0 = name_0.offset(1); let newA = hash_insert!( - oldParser, &mut (*newDtd).attributeIds, name_0 as *mut XML_Char, ATTRIBUTE_ID @@ -9091,7 +8985,6 @@ unsafe extern "C" fn dtdCopy( return 0i32; } let newE = hash_insert!( - oldParser, &mut (*newDtd).elementTypes, name_1, ELEMENT_TYPE @@ -9100,10 +8993,8 @@ unsafe extern "C" fn dtdCopy( return 0i32; } if (*oldE).nDefaultAtts != 0 { - (*newE).defaultAtts = (*ms).malloc_fcn.expect("non-null function pointer")( - ((*oldE).nDefaultAtts as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong), - ) as *mut DEFAULT_ATTRIBUTE; + (*newE).defaultAtts = alloc::alloc(malloc_array_layout::( + (*oldE).nDefaultAtts as usize)) as *mut DEFAULT_ATTRIBUTE; if (*newE).defaultAtts.is_null() { return 0i32; } @@ -9148,7 +9039,6 @@ unsafe extern "C" fn dtdCopy( } /* Copy the entity tables. */ if copyEntityTable( - oldParser, &mut (*newDtd).generalEntities, &mut (*newDtd).pool, &(*oldDtd).generalEntities, @@ -9157,7 +9047,6 @@ unsafe extern "C" fn dtdCopy( return 0i32; } if copyEntityTable( - oldParser, &mut (*newDtd).paramEntities, &mut (*newDtd).pool, &(*oldDtd).paramEntities, @@ -9182,10 +9071,9 @@ unsafe extern "C" fn dtdCopy( /* End dtdCopy */ unsafe extern "C" fn copyEntityTable( - mut oldParser: XML_Parser, - mut newTable: &mut HashMap>, + mut newTable: &mut HashMap>, mut newPool: *mut STRING_POOL, - mut oldTable: &HashMap>, + mut oldTable: &HashMap>, ) -> c_int { let mut cachedOldBase: *const XML_Char = NULL as *const XML_Char; let mut cachedNewBase: *const XML_Char = NULL as *const XML_Char; @@ -9196,7 +9084,6 @@ unsafe extern "C" fn copyEntityTable( return 0i32; } let newE = hash_insert!( - oldParser, &mut newTable, name, ENTITY @@ -9306,14 +9193,12 @@ impl XML_ParserStruct { impl STRING_POOL { unsafe fn init( &mut self, - mut ms: *const XML_Memory_Handling_Suite, ) { self.blocks = NULL as *mut BLOCK; self.freeBlocks = NULL as *mut BLOCK; self.start = NULL as *mut XML_Char; self.ptr = NULL as *mut XML_Char; self.end = NULL as *const XML_Char; - self.mem = ms; } unsafe fn clear(&mut self) { @@ -9338,13 +9223,13 @@ impl STRING_POOL { let mut p: *mut BLOCK = self.blocks; while !p.is_null() { let mut tem: *mut BLOCK = (*p).next; - (*self.mem).free_fcn.expect("non-null function pointer")(p as *mut c_void); + FREE!(p); p = tem } p = self.freeBlocks; while !p.is_null() { let mut tem_0: *mut BLOCK = (*p).next; - (*self.mem).free_fcn.expect("non-null function pointer")(p as *mut c_void); + FREE!(p); p = tem_0 } } @@ -9550,12 +9435,7 @@ impl STRING_POOL { if bytesToAllocate == 0 { return XML_FALSE; } - temp = (*self.mem) - .realloc_fcn - .expect("non-null function pointer")( - self.blocks as *mut c_void, - bytesToAllocate as c_uint as size_t, - ) as *mut BLOCK; + temp = REALLOC!(self.blocks, bytesToAllocate as usize) as *mut BLOCK; if temp.is_null() { return XML_FALSE; } @@ -9597,9 +9477,7 @@ impl STRING_POOL { if bytesToAllocate_0 == 0 { return XML_FALSE; } /* save one level of indirection */ - tem_0 = (*self.mem) - .malloc_fcn - .expect("non-null function pointer")(bytesToAllocate_0) as *mut BLOCK; + tem_0 = MALLOC!(bytesToAllocate_0) as *mut BLOCK; if tem_0.is_null() { return XML_FALSE; } @@ -9632,7 +9510,6 @@ impl XML_ParserStruct { let mut next: c_int = 0; if (*dtd).scaffIndex.is_null() { (*dtd).scaffIndex = MALLOC!( - self, (self.m_groupSize as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut c_int; @@ -9645,7 +9522,6 @@ impl XML_ParserStruct { let mut temp: *mut CONTENT_SCAFFOLD = 0 as *mut CONTENT_SCAFFOLD; if !(*dtd).scaffold.is_null() { temp = REALLOC!( - self, (*dtd).scaffold as *mut c_void, ((*dtd).scaffSize.wrapping_mul(2u32) as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong) @@ -9656,7 +9532,6 @@ impl XML_ParserStruct { (*dtd).scaffSize = (*dtd).scaffSize.wrapping_mul(2u32) } else { temp = MALLOC!( - self, 32u64.wrapping_mul(::std::mem::size_of::() as c_ulong) ) as *mut CONTENT_SCAFFOLD; if temp.is_null() { @@ -9749,7 +9624,7 @@ impl XML_ParserStruct { ((*dtd).contentStringLen as c_ulong) .wrapping_mul(::std::mem::size_of::() as c_ulong), ) as c_int; - ret = MALLOC!(self, allocsize as size_t) as *mut XML_Content; + ret = MALLOC!(allocsize as size_t) as *mut XML_Content; if ret.is_null() { return NULL as *mut XML_Content; } @@ -9772,7 +9647,6 @@ impl XML_ParserStruct { return NULL as *mut ELEMENT_TYPE; } let ret = hash_insert!( - self, &mut (*dtd).elementTypes, name, ELEMENT_TYPE @@ -9794,7 +9668,6 @@ impl XML_ParserStruct { unsafe extern "C" fn copyString( mut s: *const XML_Char, - mut memsuite: *const XML_Memory_Handling_Suite, ) -> *mut XML_Char { let mut charsRequired: c_int = 0; let mut result: *mut XML_Char = 0 as *mut XML_Char; @@ -9805,9 +9678,8 @@ unsafe extern "C" fn copyString( /* Include the terminator */ charsRequired += 1; /* Now allocate space for the copy */ - result = (*memsuite).malloc_fcn.expect("non-null function pointer")( - (charsRequired as c_ulong).wrapping_mul(::std::mem::size_of::() as c_ulong), - ) as *mut XML_Char; + result = alloc::alloc(malloc_array_layout::(charsRequired as usize)) + as *mut XML_Char; if result.is_null() { return NULL as *mut XML_Char; } diff --git a/src/tests/runtests.rs b/src/tests/runtests.rs index 282b4fa..e45e77a 100644 --- a/src/tests/runtests.rs +++ b/src/tests/runtests.rs @@ -46,7 +46,8 @@ label_break_value, main, ptr_wrapping_offset_from, - register_tool + register_tool, + allocator_api )] #[cfg(all(feature = "unicode", not(feature = "unicode_wchar_t")))] @@ -55,7 +56,7 @@ compile_error!("Tests are not compatible with feature \"unicode\" without 16-bit use crate::stdlib::{stderr, strncmp}; use ::rexpat::ascii_h::{ASCII_0, ASCII_9, ASCII_PERIOD}; use ::rexpat::expat_h::{ - XML_Encoding, XML_Expat_Version, XML_Feature, XML_Memory_Handling_Suite, XML_ParserStruct, + XML_Encoding, XML_Expat_Version, XML_Feature, XML_ParserStruct, XML_ParsingStatus, XML_ERROR_ABORTED, XML_ERROR_ASYNC_ENTITY, XML_ERROR_BAD_CHAR_REF, XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, XML_ERROR_DUPLICATE_ATTRIBUTE, XML_ERROR_EXTERNAL_ENTITY_HANDLING, XML_ERROR_FINISHED, XML_ERROR_INCORRECT_ENCODING, @@ -99,7 +100,8 @@ use ::rexpat::stdlib::{__assert_fail, fprintf, malloc, memcmp, memcpy, realloc, pub use ::rexpat::*; use ::libc::{free, printf, sprintf, strcmp, EXIT_FAILURE, EXIT_SUCCESS}; -use ::std::mem::transmute; +use std::alloc::{GlobalAlloc, Layout, System}; +use std::mem::transmute; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void}; @@ -650,9 +652,86 @@ pub struct DataIssue240 { /* XML_UNICODE */ /* XML_UNICODE_WCHAR_T */ +struct Allocator; + +enum AllocatorMode { + System, + Duff, + Tracking, +} + +#[global_allocator] +static ALLOCATOR: Allocator = Allocator; +static SYSTEM_ALLOCATOR: System = System; +static mut ALLOCATOR_MODE: AllocatorMode = AllocatorMode::System; + +unsafe impl GlobalAlloc for Allocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let ptr = match ALLOCATOR_MODE { + AllocatorMode::System => { + return SYSTEM_ALLOCATOR.alloc(layout); + } + AllocatorMode::Duff => { + duff_allocator(layout.size() as size_t) as *mut u8 + } + AllocatorMode::Tracking => { + crate::memcheck::tracking_malloc(layout.size() as size_t) as *mut u8 + } + }; + if ptr.align_offset(layout.align()) == 0 { + ptr + } else { + self.dealloc(ptr, layout); + std::ptr::null_mut() + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + match ALLOCATOR_MODE { + AllocatorMode::System => { + SYSTEM_ALLOCATOR.dealloc(ptr, layout); + } + AllocatorMode::Duff => { + free(ptr as *mut _); + } + AllocatorMode::Tracking => { + crate::memcheck::tracking_free(ptr as *mut _); + } + } + } + + unsafe fn realloc( + &self, + ptr: *mut u8, + layout: Layout, + new_size: usize + ) -> *mut u8 { + let ptr = match ALLOCATOR_MODE { + AllocatorMode::System => { + return SYSTEM_ALLOCATOR.realloc(ptr, layout, new_size); + } + AllocatorMode::Duff => { + duff_reallocator(ptr as *mut _, + new_size as size_t) as *mut u8 + } + AllocatorMode::Tracking => { + crate::memcheck::tracking_realloc(ptr as *mut _, + new_size as size_t) as *mut u8 + } + }; + if ptr.align_offset(layout.align()) == 0 { + ptr + } else { + self.dealloc(ptr, layout); + std::ptr::null_mut() + } + } +} + static mut g_parser: XML_Parser = ::rexpat::stddef_h::NULL as XML_Parser; unsafe extern "C" fn basic_setup() { + ALLOCATOR_MODE = AllocatorMode::System; g_parser = XML_ParserCreate(::rexpat::stddef_h::NULL as *const XML_Char); if g_parser.is_null() { crate::minicheck::_fail_unless( @@ -668,6 +747,9 @@ unsafe extern "C" fn basic_setup() { unsafe extern "C" fn basic_teardown() { if !g_parser.is_null() { XML_ParserFree(g_parser); + // Switch to system allocator to prevent the tests' own allocations + // from going to the Duff or tracking allocators + ALLOCATOR_MODE = AllocatorMode::System; g_parser = ::rexpat::stddef_h::NULL as XML_Parser }; } @@ -16135,16 +16217,7 @@ unsafe extern "C" fn test_misc_alloc_create_parser() { as *const c_char, 7205, ); - let mut memsuite: XML_Memory_Handling_Suite = { - let mut init = XML_Memory_Handling_Suite { - malloc_fcn: Some(duff_allocator as unsafe extern "C" fn(_: size_t) -> *mut c_void), - realloc_fcn: Some( - realloc as unsafe extern "C" fn(_: *mut c_void, _: c_ulong) -> *mut c_void, - ), - free_fcn: Some(free as unsafe extern "C" fn(_: *mut c_void) -> ()), - }; - init - }; + ALLOCATOR_MODE = AllocatorMode::Duff; let mut i: c_uint = 0; let max_alloc_count: c_uint = 10; /* Something this simple shouldn't need more than 10 allocations */ @@ -16153,7 +16226,7 @@ unsafe extern "C" fn test_misc_alloc_create_parser() { allocation_count = i as intptr_t; g_parser = XML_ParserCreate_MM( ::rexpat::stddef_h::NULL as *const XML_Char, - Some(&memsuite), + None, ::rexpat::stddef_h::NULL as *const XML_Char, ); if !g_parser.is_null() { @@ -16191,16 +16264,7 @@ unsafe extern "C" fn test_misc_alloc_create_parser_with_encoding() { as *const c_char, 7225, ); - let mut memsuite: XML_Memory_Handling_Suite = { - let mut init = XML_Memory_Handling_Suite { - malloc_fcn: Some(duff_allocator as unsafe extern "C" fn(_: size_t) -> *mut c_void), - realloc_fcn: Some( - realloc as unsafe extern "C" fn(_: *mut c_void, _: c_ulong) -> *mut c_void, - ), - free_fcn: Some(free as unsafe extern "C" fn(_: *mut c_void) -> ()), - }; - init - }; + ALLOCATOR_MODE = AllocatorMode::Duff; let mut i: c_uint = 0; let max_alloc_count: c_uint = 10; /* Try several levels of allocation */ @@ -16209,7 +16273,7 @@ unsafe extern "C" fn test_misc_alloc_create_parser_with_encoding() { allocation_count = i as intptr_t; g_parser = XML_ParserCreate_MM( b"us-ascii\x00".as_ptr() as *const c_char, - Some(&memsuite), + None, ::rexpat::stddef_h::NULL as *const XML_Char, ); if !g_parser.is_null() { @@ -16484,24 +16548,10 @@ unsafe extern "C" fn test_misc_attribute_leak() { ); let mut text: *const c_char = b"\x00".as_ptr() as *const c_char; - let mut memsuite: XML_Memory_Handling_Suite = { - let mut init = XML_Memory_Handling_Suite { - malloc_fcn: Some( - crate::memcheck::tracking_malloc as unsafe extern "C" fn(_: size_t) -> *mut c_void, - ), - realloc_fcn: Some( - crate::memcheck::tracking_realloc - as unsafe extern "C" fn(_: *mut c_void, _: size_t) -> *mut c_void, - ), - free_fcn: Some( - crate::memcheck::tracking_free as unsafe extern "C" fn(_: *mut c_void) -> (), - ), - }; - init - }; + ALLOCATOR_MODE = AllocatorMode::Tracking; g_parser = XML_ParserCreate_MM( b"UTF-8\x00".as_ptr() as *const c_char, - Some(&memsuite), + None, b"\n\x00".as_ptr() as *const c_char, ); _expect_failure( @@ -16785,22 +16835,13 @@ unsafe extern "C" fn test_misc_deny_internal_entity_closing_doctype_issue_317() } unsafe extern "C" fn alloc_setup() { - let mut memsuite: XML_Memory_Handling_Suite = { - let mut init = XML_Memory_Handling_Suite { - malloc_fcn: Some(duff_allocator as unsafe extern "C" fn(_: size_t) -> *mut c_void), - realloc_fcn: Some( - duff_reallocator as unsafe extern "C" fn(_: *mut c_void, _: size_t) -> *mut c_void, - ), - free_fcn: Some(free as unsafe extern "C" fn(_: *mut c_void) -> ()), - }; - init - }; + ALLOCATOR_MODE = AllocatorMode::Duff; /* Ensure the parser creation will go through */ allocation_count = ALLOC_ALWAYS_SUCCEED as intptr_t; reallocation_count = REALLOC_ALWAYS_SUCCEED as intptr_t; g_parser = XML_ParserCreate_MM( ::rexpat::stddef_h::NULL as *const XML_Char, - Some(&memsuite), + None, ::rexpat::stddef_h::NULL as *const XML_Char, ); if g_parser.is_null() { @@ -20519,23 +20560,14 @@ unsafe extern "C" fn test_alloc_long_notation() { } unsafe extern "C" fn nsalloc_setup() { - let mut memsuite: XML_Memory_Handling_Suite = { - let mut init = XML_Memory_Handling_Suite { - malloc_fcn: Some(duff_allocator as unsafe extern "C" fn(_: size_t) -> *mut c_void), - realloc_fcn: Some( - duff_reallocator as unsafe extern "C" fn(_: *mut c_void, _: size_t) -> *mut c_void, - ), - free_fcn: Some(free as unsafe extern "C" fn(_: *mut c_void) -> ()), - }; - init - }; + ALLOCATOR_MODE = AllocatorMode::Duff; let mut ns_sep: [XML_Char; 2] = [' ' as XML_Char, '\u{0}' as XML_Char]; /* Ensure the parser creation will go through */ allocation_count = ALLOC_ALWAYS_SUCCEED as intptr_t; reallocation_count = REALLOC_ALWAYS_SUCCEED as intptr_t; g_parser = XML_ParserCreate_MM( ::rexpat::stddef_h::NULL as *const XML_Char, - Some(&memsuite), + None, ns_sep.as_mut_ptr(), ); if g_parser.is_null() { From 881affe6ad7b4dd50b9c155fe547526192e1c66d Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 14:54:07 -0800 Subject: [PATCH 02/19] Add comment on alignment requirements --- src/tests/runtests.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/runtests.rs b/src/tests/runtests.rs index e45e77a..bdd7b8a 100644 --- a/src/tests/runtests.rs +++ b/src/tests/runtests.rs @@ -678,6 +678,9 @@ unsafe impl GlobalAlloc for Allocator { crate::memcheck::tracking_malloc(layout.size() as size_t) as *mut u8 } }; + // Check Rust's alignment requirements, + // and abort the allocation if they can't be met + // Alternatively, we could panic instead if ptr.align_offset(layout.align()) == 0 { ptr } else { From 0f4179d3e515338069b1188e60f0ccae34acb5a6 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 17:26:06 -0800 Subject: [PATCH 03/19] Remove casts for FREE macro calls --- src/lib/xmlparse.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index d59efc4..37bcb33 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1657,7 +1657,7 @@ impl XML_ParserStruct { } self.m_tempPool.clear(); self.m_temp2Pool.clear(); - FREE!(self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName); self.m_protocolEncodingName = NULL as *const XML_Char; self.init(encodingName); dtdReset(self.m_dtd); @@ -1693,7 +1693,7 @@ impl XML_ParserStruct { } /* Get rid of any previous encoding name */ - FREE!(self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName); if encodingName.is_null() { /* No new encoding name */ self.m_protocolEncodingName = NULL as *const XML_Char @@ -1910,8 +1910,8 @@ unsafe fn destroyBindings(mut bindings: *mut BINDING) { break; } bindings = (*b).nextTagBinding; - FREE!((*b).uri as *mut c_void); - FREE!(b as *mut c_void); + FREE!((*b).uri); + FREE!(b); } } @@ -1934,7 +1934,7 @@ impl Drop for XML_ParserStruct { } p = tagList; tagList = (*tagList).parent; - FREE!((*p).buf as *mut c_void); + FREE!((*p).buf); destroyBindings((*p).bindings); } /* free m_openInternalEntities and m_freeInternalEntities */ @@ -1950,13 +1950,13 @@ impl Drop for XML_ParserStruct { } openEntity = entityList; entityList = (*entityList).next; - FREE!(openEntity as *mut c_void); + FREE!(openEntity); } destroyBindings(self.m_freeBindingList); destroyBindings(self.m_inheritedBindings); self.m_tempPool.destroy(); self.m_temp2Pool.destroy(); - FREE!(self.m_protocolEncodingName as *mut c_void); + FREE!(self.m_protocolEncodingName); /* external parameter entity parsers share the DTD structure parser->m_dtd with the root parser, so we must not destroy it */ @@ -1967,11 +1967,11 @@ impl Drop for XML_ParserStruct { self.m_parentParser.is_null() as XML_Bool, ); } - FREE!(self.m_atts as *mut c_void); - FREE!(self.m_groupConnector as *mut c_void); - FREE!(self.m_buffer as *mut c_void); - FREE!(self.m_dataBuf as *mut c_void); - FREE!(self.m_nsAtts as *mut c_void); + FREE!(self.m_atts); + FREE!(self.m_groupConnector); + FREE!(self.m_buffer); + FREE!(self.m_dataBuf); + FREE!(self.m_nsAtts); if self.m_unknownEncodingRelease.is_some() { self.m_unknownEncodingRelease .expect("non-null function pointer")(self.m_unknownEncodingData); @@ -2807,7 +2807,7 @@ impl XML_ParserStruct { 0 }) + keep as c_long) as c_ulong, ); - FREE!(self.m_buffer as *mut c_void); + FREE!(self.m_buffer); self.m_buffer = newBuf; self.m_bufferEnd = self .m_buffer @@ -3139,7 +3139,7 @@ pub unsafe extern "C" fn XML_GetCurrentColumnNumber(mut parser: XML_Parser) -> X #[no_mangle] pub unsafe extern "C" fn XML_FreeContentModel(mut parser: XML_Parser, mut model: *mut XML_Content) { if !parser.is_null() { - FREE!(model as *mut c_void); + FREE!(model); }; } /* Exposing the memory handling functions used in Expat */ @@ -3778,7 +3778,7 @@ impl XML_ParserStruct { } (*tag).buf = MALLOC!(32u64) as *mut c_char; if (*tag).buf.is_null() { - FREE!(tag as *mut c_void); + FREE!(tag); return XML_ERROR_NO_MEMORY; } (*tag).bufEnd = (*tag).buf.offset(INIT_TAG_BUF_SIZE as isize) @@ -4859,7 +4859,7 @@ impl XML_ParserStruct { } p = (*p).parent } - FREE!((*binding).uri as *mut c_void); + FREE!((*binding).uri); (*binding).uri = uri } /* if m_namespaceSeparator != '\0' then uri includes it already */ @@ -5050,7 +5050,7 @@ unsafe extern "C" fn addBinding( (::std::mem::size_of::() as c_ulong).wrapping_mul((len + 24) as c_ulong) ) as *mut XML_Char; if (*b).uri.is_null() { - FREE!(b as *mut c_void); + FREE!(b); return XML_ERROR_NO_MEMORY; } (*b).uriAlloc = len + EXPAND_SPARE From 0f45eea4c650999c280d7e346fd26fcea455ce87 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 17:42:00 -0800 Subject: [PATCH 04/19] Add MALLOC![T; N] form of MALLOC macro that allocates arrays of a given type --- src/lib/xmlparse.rs | 68 ++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 44 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 37bcb33..9ee5212 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1075,25 +1075,24 @@ pub const EXPAND_SPARE: c_int = 24; pub const INIT_SCAFFOLD_ELEMENTS: c_int = 32; -fn malloc_layout(size: usize) -> Layout { - Layout::from_size_align(size, 1) - .expect("failed to create Layout") -} - -fn malloc_array_layout(n: usize) -> Layout { - Layout::array::(n as usize) - .expect("failed to create array Layout") -} - macro_rules! MALLOC { - ($size:expr $(,)?) => { - alloc::alloc(malloc_layout($size as usize)) as *mut c_void - }; + ($size:expr $(,)?) => {{ + let layout = Layout::from_size_align($size as usize, 1) + .expect("failed to create Layout"); + alloc::alloc(layout) as *mut c_void + }}; + [$ty:ty; $n:expr] => {{ + let layout = Layout::array::<$ty>($n as usize) + .expect("failed to create array Layout"); + alloc::alloc(layout) as *mut $ty + }} } macro_rules! REALLOC { - ($ptr:expr, $size:expr $(,)?) => { - alloc::realloc($ptr as *mut u8, malloc_layout($size as usize), $size as usize) as *mut c_void - }; + ($ptr:expr, $size:expr $(,)?) => {{ + let layout = Layout::from_size_align($size as usize, 1) + .expect("failed to create Layout"); + alloc::realloc($ptr as *mut u8, layout, $size as usize) as *mut c_void + }}; } macro_rules! FREE { ($ptr:expr $(,)?) => { @@ -1490,16 +1489,11 @@ impl XML_ParserStruct { parser.m_buffer = NULL as *mut c_char; parser.m_bufferLim = NULL as *const c_char; parser.m_attsSize = INIT_ATTS_SIZE; - parser.m_atts = MALLOC!( - (parser.m_attsSize as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut super::xmltok::ATTRIBUTE; + parser.m_atts = MALLOC![super::xmltok::ATTRIBUTE; parser.m_attsSize]; if parser.m_atts.is_null() { return ptr::null_mut(); } - parser.m_dataBuf = MALLOC!( - 1024u64.wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut XML_Char; + parser.m_dataBuf = MALLOC![XML_Char; 1024]; if parser.m_dataBuf.is_null() { return ptr::null_mut(); } @@ -4839,9 +4833,7 @@ impl XML_ParserStruct { n = i + (*binding).uriLen + prefixLen; if n > (*binding).uriAlloc { let mut p: *mut TAG = 0 as *mut TAG; - uri = MALLOC!( - ((n + 24) as c_ulong).wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut XML_Char; + uri = MALLOC![XML_Char; n + 24]; if uri.is_null() { return XML_ERROR_NO_MEMORY; } @@ -5046,9 +5038,7 @@ unsafe extern "C" fn addBinding( if b.is_null() { return XML_ERROR_NO_MEMORY; } - (*b).uri = MALLOC!( - (::std::mem::size_of::() as c_ulong).wrapping_mul((len + 24) as c_ulong) - ) as *mut XML_Char; + (*b).uri = MALLOC![XML_Char; len + 24]; if (*b).uri.is_null() { FREE!(b); return XML_ERROR_NO_MEMORY; @@ -8238,10 +8228,7 @@ unsafe extern "C" fn defineAttribute( if (*type_0).nDefaultAtts == (*type_0).allocDefaultAtts { if (*type_0).allocDefaultAtts == 0 { (*type_0).allocDefaultAtts = 8; - (*type_0).defaultAtts = MALLOC!( - ((*type_0).allocDefaultAtts as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut DEFAULT_ATTRIBUTE; + (*type_0).defaultAtts = MALLOC![DEFAULT_ATTRIBUTE; (*type_0).allocDefaultAtts]; if (*type_0).defaultAtts.is_null() { (*type_0).allocDefaultAtts = 0; return 0i32; @@ -8993,8 +8980,7 @@ unsafe extern "C" fn dtdCopy( return 0i32; } if (*oldE).nDefaultAtts != 0 { - (*newE).defaultAtts = alloc::alloc(malloc_array_layout::( - (*oldE).nDefaultAtts as usize)) as *mut DEFAULT_ATTRIBUTE; + (*newE).defaultAtts = MALLOC![DEFAULT_ATTRIBUTE; (*oldE).nDefaultAtts]; if (*newE).defaultAtts.is_null() { return 0i32; } @@ -9509,10 +9495,7 @@ impl XML_ParserStruct { let mut me: *mut CONTENT_SCAFFOLD = 0 as *mut CONTENT_SCAFFOLD; let mut next: c_int = 0; if (*dtd).scaffIndex.is_null() { - (*dtd).scaffIndex = MALLOC!( - (self.m_groupSize as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut c_int; + (*dtd).scaffIndex = MALLOC![c_int; self.m_groupSize]; if (*dtd).scaffIndex.is_null() { return -(1i32); } @@ -9531,9 +9514,7 @@ impl XML_ParserStruct { } (*dtd).scaffSize = (*dtd).scaffSize.wrapping_mul(2u32) } else { - temp = MALLOC!( - 32u64.wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut CONTENT_SCAFFOLD; + temp = MALLOC![CONTENT_SCAFFOLD; 32]; if temp.is_null() { return -(1i32); } @@ -9678,8 +9659,7 @@ unsafe extern "C" fn copyString( /* Include the terminator */ charsRequired += 1; /* Now allocate space for the copy */ - result = alloc::alloc(malloc_array_layout::(charsRequired as usize)) - as *mut XML_Char; + result = MALLOC![XML_Char; charsRequired]; if result.is_null() { return NULL as *mut XML_Char; } From fbfd0021dfd3c20acf231e1c16aac5a9425c1789 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 18:05:37 -0800 Subject: [PATCH 05/19] Add MALLOC!(@T) form that allocates a single object of the given type --- src/lib/xmlparse.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 9ee5212..fa1c05e 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1081,11 +1081,16 @@ macro_rules! MALLOC { .expect("failed to create Layout"); alloc::alloc(layout) as *mut c_void }}; + // FIXME: we need the @ to disambiguate from the previous form + (@$ty:ty) => {{ + let layout = Layout::new::<$ty>(); + alloc::alloc(layout) as *mut $ty + }}; [$ty:ty; $n:expr] => {{ let layout = Layout::array::<$ty>($n as usize) .expect("failed to create array Layout"); alloc::alloc(layout) as *mut $ty - }} + }}; } macro_rules! REALLOC { ($ptr:expr, $size:expr $(,)?) => {{ @@ -3766,7 +3771,7 @@ impl XML_ParserStruct { tag = self.m_freeTagList; self.m_freeTagList = (*self.m_freeTagList).parent } else { - tag = MALLOC!(::std::mem::size_of::() as c_ulong) as *mut TAG; + tag = MALLOC!(@TAG); if tag.is_null() { return XML_ERROR_NO_MEMORY; } @@ -5034,7 +5039,7 @@ unsafe extern "C" fn addBinding( } (*parser).m_freeBindingList = (*b).nextTagBinding } else { - b = MALLOC!(::std::mem::size_of::() as c_ulong) as *mut BINDING; + b = MALLOC!(@BINDING); if b.is_null() { return XML_ERROR_NO_MEMORY; } @@ -6970,9 +6975,7 @@ impl XML_ParserStruct { 41 | 42 => { if (*dtd).in_eldecl != 0 { if self.m_handlers.hasElementDecl() { - let mut content: *mut XML_Content = - MALLOC!(::std::mem::size_of::() as c_ulong) - as *mut XML_Content; + let mut content: *mut XML_Content = MALLOC!(@XML_Content); if content.is_null() { return XML_ERROR_NO_MEMORY; } @@ -7339,9 +7342,7 @@ impl XML_ParserStruct { openEntity = self.m_freeInternalEntities; self.m_freeInternalEntities = (*openEntity).next } else { - openEntity = MALLOC!( - ::std::mem::size_of::() as c_ulong - ) as *mut OPEN_INTERNAL_ENTITY; + openEntity = MALLOC!(@OPEN_INTERNAL_ENTITY); if openEntity.is_null() { return XML_ERROR_NO_MEMORY; } From 5b429c07e25bde3fbcd300f17dcb0a8e89ff078c Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 18:09:31 -0800 Subject: [PATCH 06/19] Replace some more raw MALLOCs with the array form --- src/lib/xmlparse.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index fa1c05e..dc018d5 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -2787,7 +2787,7 @@ impl XML_ParserStruct { self.m_errorCode = XML_ERROR_NO_MEMORY; return NULL as *mut c_void; } - newBuf = MALLOC!(bufferSize as size_t) as *mut c_char; + newBuf = MALLOC![c_char; bufferSize]; if newBuf.is_null() { self.m_errorCode = XML_ERROR_NO_MEMORY; return NULL as *mut c_void; @@ -3775,7 +3775,7 @@ impl XML_ParserStruct { if tag.is_null() { return XML_ERROR_NO_MEMORY; } - (*tag).buf = MALLOC!(32u64) as *mut c_char; + (*tag).buf = MALLOC![c_char; 32]; if (*tag).buf.is_null() { FREE!(tag); return XML_ERROR_NO_MEMORY; @@ -6741,8 +6741,7 @@ impl XML_ParserStruct { } } else { self.m_groupSize = 32u32; - self.m_groupConnector = - MALLOC!(self.m_groupSize as size_t) as *mut c_char; + self.m_groupConnector = MALLOC![c_char; self.m_groupSize]; if self.m_groupConnector.is_null() { self.m_groupSize = 0u32; return XML_ERROR_NO_MEMORY; From faf09052ac750b9836c9ca881253d5e9fe96dc0d Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 18:32:27 -0800 Subject: [PATCH 07/19] Add type-safe version of REALLOC macro that uses Layout --- src/lib/xmlparse.rs | 56 +++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index dc018d5..22f3d2a 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1098,6 +1098,13 @@ macro_rules! REALLOC { .expect("failed to create Layout"); alloc::realloc($ptr as *mut u8, layout, $size as usize) as *mut c_void }}; + ($ptr:expr => [$ty:ty; $n:expr]) => {{ + // FIXME: we should pass the old `Layout` to `realloc`, + // but we don't have it + let layout = Layout::array::<$ty>($n as usize) + .expect("failed to create array Layout"); + alloc::realloc($ptr as *mut u8, layout, layout.size()) as *mut $ty + }}; } macro_rules! FREE { ($ptr:expr $(,)?) => { @@ -3386,8 +3393,7 @@ impl XML_ParserStruct { & !(::std::mem::size_of::() as c_ulong).wrapping_sub(1u64), ) as c_int; if bufSize as c_long > (*tag).bufEnd.wrapping_offset_from((*tag).buf) as c_long { - let mut temp: *mut c_char = - REALLOC!((*tag).buf as *mut c_void, bufSize as size_t) as *mut c_char; + let mut temp = REALLOC!((*tag).buf => [c_char; bufSize]); if temp.is_null() { return XML_FALSE; } @@ -3812,9 +3818,7 @@ impl XML_ParserStruct { break; } else { bufSize = ((*tag).bufEnd.wrapping_offset_from((*tag).buf) as c_int) << 1; - let mut temp: *mut c_char = - REALLOC!((*tag).buf as *mut c_void, bufSize as size_t) - as *mut c_char; + let mut temp = REALLOC!((*tag).buf => [c_char; bufSize]); if temp.is_null() { return XML_ERROR_NO_MEMORY; } @@ -4265,11 +4269,7 @@ impl XML_ParserStruct { let mut oldAttsSize: c_int = self.m_attsSize; let mut temp: *mut super::xmltok::ATTRIBUTE = 0 as *mut super::xmltok::ATTRIBUTE; self.m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - temp = REALLOC!( - self.m_atts as *mut c_void, - (self.m_attsSize as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut super::xmltok::ATTRIBUTE; + temp = REALLOC!(self.m_atts => [super::xmltok::ATTRIBUTE; self.m_attsSize]); if temp.is_null() { self.m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; @@ -4485,10 +4485,7 @@ impl XML_ParserStruct { self.m_nsAttsPower = 3u8 } nsAttsSize = (1) << self.m_nsAttsPower as c_int; - temp_0 = REALLOC!( - self.m_nsAtts as *mut c_void, - (nsAttsSize as c_ulong).wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut NS_ATT; + temp_0 = REALLOC!(self.m_nsAtts => [NS_ATT; nsAttsSize]); if temp_0.is_null() { /* Restore actual size of memory in m_nsAtts */ self.m_nsAttsPower = oldNsAttsPower; @@ -5027,10 +5024,7 @@ unsafe extern "C" fn addBinding( if !(*parser).m_freeBindingList.is_null() { b = (*parser).m_freeBindingList; if len > (*b).uriAlloc { - let mut temp: *mut XML_Char = REALLOC!( - (*b).uri as *mut c_void, - (::std::mem::size_of::() as c_ulong).wrapping_mul((len + 24) as c_ulong) - ) as *mut XML_Char; + let mut temp: *mut XML_Char = REALLOC!((*b).uri => [XML_Char; len + 24]); if temp.is_null() { return XML_ERROR_NO_MEMORY; } @@ -6718,10 +6712,8 @@ impl XML_ParserStruct { if self.m_prologState.level >= self.m_groupSize { if self.m_groupSize != 0 { self.m_groupSize = self.m_groupSize.wrapping_mul(2u32); - let new_connector: *mut c_char = REALLOC!( - self.m_groupConnector as *mut c_void, - self.m_groupSize as size_t - ) as *mut c_char; + let new_connector = REALLOC!( + self.m_groupConnector => [c_char; self.m_groupSize]); if new_connector.is_null() { self.m_groupSize = self.m_groupSize.wrapping_div(2u32); return XML_ERROR_NO_MEMORY; @@ -6729,11 +6721,7 @@ impl XML_ParserStruct { self.m_groupConnector = new_connector; if !(*dtd).scaffIndex.is_null() { let new_scaff_index: *mut c_int = REALLOC!( - (*dtd).scaffIndex as *mut c_void, - (self.m_groupSize as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) - as *mut c_int; + (*dtd).scaffIndex => [c_int; self.m_groupSize]); if new_scaff_index.is_null() { return XML_ERROR_NO_MEMORY; } @@ -8236,11 +8224,7 @@ unsafe extern "C" fn defineAttribute( } else { let mut temp: *mut DEFAULT_ATTRIBUTE = 0 as *mut DEFAULT_ATTRIBUTE; let mut count: c_int = (*type_0).allocDefaultAtts * 2; - temp = REALLOC!( - (*type_0).defaultAtts as *mut c_void, - (count as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut DEFAULT_ATTRIBUTE; + temp = REALLOC!((*type_0).defaultAtts => [DEFAULT_ATTRIBUTE; count]); if temp.is_null() { return 0i32; } @@ -9421,7 +9405,7 @@ impl STRING_POOL { if bytesToAllocate == 0 { return XML_FALSE; } - temp = REALLOC!(self.blocks, bytesToAllocate as usize) as *mut BLOCK; + temp = REALLOC!(self.blocks, bytesToAllocate) as *mut BLOCK; if temp.is_null() { return XML_FALSE; } @@ -9504,11 +9488,7 @@ impl XML_ParserStruct { if (*dtd).scaffCount >= (*dtd).scaffSize { let mut temp: *mut CONTENT_SCAFFOLD = 0 as *mut CONTENT_SCAFFOLD; if !(*dtd).scaffold.is_null() { - temp = REALLOC!( - (*dtd).scaffold as *mut c_void, - ((*dtd).scaffSize.wrapping_mul(2u32) as c_ulong) - .wrapping_mul(::std::mem::size_of::() as c_ulong) - ) as *mut CONTENT_SCAFFOLD; + temp = REALLOC!((*dtd).scaffold => [CONTENT_SCAFFOLD; (*dtd).scaffSize.wrapping_mul(2u32)]); if temp.is_null() { return -(1i32); } From 48c2fbb2008fa887aa59c374aa4950a1e5d26dac Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 4 Feb 2020 18:37:27 -0800 Subject: [PATCH 08/19] Replace direct calls to allocation functions with calls to MALLOC/FREE macros --- src/lib/xmlparse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 22f3d2a..9b2d6a5 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -8794,7 +8794,7 @@ unsafe extern "C" fn normalizePublicId(mut publicId: *mut XML_Char) { } unsafe extern "C" fn dtdCreate() -> *mut DTD { - let mut p: *mut DTD = alloc::alloc(Layout::new::()) as *mut DTD; + let mut p: *mut DTD = MALLOC!(@DTD); if p.is_null() { return p; } @@ -8876,7 +8876,7 @@ unsafe extern "C" fn dtdDestroy( FREE!((*p).scaffIndex); FREE!((*p).scaffold); } - alloc::dealloc(p as *mut u8, Layout::new::()); + FREE!(p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. The new DTD has already been initialized. From 101112a20ac673208cdf563089075d4190218b42 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 11:01:31 -0800 Subject: [PATCH 09/19] Remove allocator_api feature from runtests.rs --- src/tests/runtests.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tests/runtests.rs b/src/tests/runtests.rs index bdd7b8a..d06daf6 100644 --- a/src/tests/runtests.rs +++ b/src/tests/runtests.rs @@ -46,8 +46,7 @@ label_break_value, main, ptr_wrapping_offset_from, - register_tool, - allocator_api + register_tool )] #[cfg(all(feature = "unicode", not(feature = "unicode_wchar_t")))] From e8a3100daa7aa05735fe97fef99a21f2639e4bef Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 18:01:10 -0800 Subject: [PATCH 10/19] Add a TODO on removing the boxes inside the hash maps --- src/lib/xmlparse.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 9b2d6a5..d282973 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -876,6 +876,9 @@ macro_rules! hash_lookup { #[repr(C)] #[derive(Clone)] pub struct DTD { + // TODO: get rid of the `Box`es to eliminate the extra indirection; + // for now, we can keep them since they're equivalent to the C code's + // structure anyway pub generalEntities: HashMap>, pub elementTypes: HashMap>, pub attributeIds: HashMap>, From 7f8507810968f9dd8d2b5aac53719670170e2639 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 18:27:57 -0800 Subject: [PATCH 11/19] Use the INIT_DATA_BUF_SIZE const instead of the numeric value when allocating m_dataBuf --- src/lib/xmlparse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 940c5fa..8f5aadf 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1508,7 +1508,7 @@ impl XML_ParserStruct { if parser.m_atts.is_null() { return ptr::null_mut(); } - parser.m_dataBuf = MALLOC![XML_Char; 1024]; + parser.m_dataBuf = MALLOC![XML_Char; INIT_DATA_BUF_SIZE]; if parser.m_dataBuf.is_null() { return ptr::null_mut(); } From cd6b377e01369ef5cdbed344d86b726feae965b2 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 18:31:17 -0800 Subject: [PATCH 12/19] Use a few more consts instead of literals in calls to MALLOC --- src/lib/xmlparse.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 8f5aadf..a28263a 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -3784,7 +3784,7 @@ impl XML_ParserStruct { if tag.is_null() { return XML_ERROR_NO_MEMORY; } - (*tag).buf = MALLOC![c_char; 32]; + (*tag).buf = MALLOC![c_char; INIT_TAG_BUF_SIZE]; if (*tag).buf.is_null() { FREE!(tag); return XML_ERROR_NO_MEMORY; @@ -4838,7 +4838,7 @@ impl XML_ParserStruct { n = i + (*binding).uriLen + prefixLen; if n > (*binding).uriAlloc { let mut p: *mut TAG = 0 as *mut TAG; - uri = MALLOC![XML_Char; n + 24]; + uri = MALLOC![XML_Char; n + EXPAND_SPARE]; if uri.is_null() { return XML_ERROR_NO_MEMORY; } @@ -5040,7 +5040,7 @@ unsafe extern "C" fn addBinding( if b.is_null() { return XML_ERROR_NO_MEMORY; } - (*b).uri = MALLOC![XML_Char; len + 24]; + (*b).uri = MALLOC![XML_Char; len + EXPAND_SPARE]; if (*b).uri.is_null() { FREE!(b); return XML_ERROR_NO_MEMORY; @@ -9497,7 +9497,7 @@ impl XML_ParserStruct { } (*dtd).scaffSize = (*dtd).scaffSize.wrapping_mul(2u32) } else { - temp = MALLOC![CONTENT_SCAFFOLD; 32]; + temp = MALLOC![CONTENT_SCAFFOLD; INIT_SCAFFOLD_ELEMENTS]; if temp.is_null() { return -(1i32); } From 51f3925d7dba1b60fbad67e849afd2f58086d7b6 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 18:33:21 -0800 Subject: [PATCH 13/19] Replace one literal with const in REALLOC macro use --- src/lib/xmlparse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index a28263a..ca325a6 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -5027,7 +5027,7 @@ unsafe extern "C" fn addBinding( if !(*parser).m_freeBindingList.is_null() { b = (*parser).m_freeBindingList; if len > (*b).uriAlloc { - let mut temp: *mut XML_Char = REALLOC!((*b).uri => [XML_Char; len + 24]); + let mut temp: *mut XML_Char = REALLOC!((*b).uri => [XML_Char; len + EXPAND_SPARE]); if temp.is_null() { return XML_ERROR_NO_MEMORY; } From 4bce612fdae81e1b11e148e1b3d271f09f3fd0b9 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 5 Feb 2020 18:56:14 -0800 Subject: [PATCH 14/19] Directly initialize m_tempPool and m_temp2Pool as members of parser --- src/lib/xmlparse.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index ca325a6..d3ac8f9 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1535,12 +1535,8 @@ impl XML_ParserStruct { parser.m_nsAttsVersion = 0; parser.m_nsAttsPower = 0; parser.m_protocolEncodingName = NULL as *const XML_Char; - - if let XML_ParserStruct {ref mut m_tempPool, ref mut m_temp2Pool, ..} = &mut *parser { - m_tempPool.init(); - m_temp2Pool.init(); - }; - + parser.m_tempPool.init(); + parser.m_temp2Pool.init(); parser.init(encodingName); if !encodingName.is_null() && parser.m_protocolEncodingName.is_null() { return ptr::null_mut(); From 32a224815fe44ac2ebb5f3ade3da4a5389f43fcf Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 6 Feb 2020 13:38:11 -0800 Subject: [PATCH 15/19] Remove OldEncoding structure --- src/lib/xmlparse.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index f3b2545..3a3cde5 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -398,13 +398,6 @@ pub enum EncodingType { Internal, } -pub enum OldEncoding { - Global(&'static dyn XmlEncoding), - Init(Box), - Unknown(Box), - Internal(&'static dyn XmlEncoding), -} - impl EncodingType { fn is_internal(&self) -> bool { match self { From f12979b3243205a3cc846107b7ae83054e4ddfd1 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 6 Feb 2020 13:54:04 -0800 Subject: [PATCH 16/19] Use unimplemented! to abort if the user passes in a custom memory allocation suite --- src/lib/xmlparse.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 3a3cde5..a0c92ad 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -1523,8 +1523,9 @@ pub unsafe extern "C" fn XML_ParserCreate_MM( mut memsuite: Option<&XML_Memory_Handling_Suite>, mut nameSep: *const XML_Char, ) -> XML_Parser { - // FIXME - assert!(memsuite.is_none()); + if memsuite.is_some() { + unimplemented!("custom memory allocators are not supported"); + } XML_ParserStruct::create(encodingName, nameSep, NULL as *mut DTD) } From 26ffcece7e08b6672b47e94a83af0ce38cf88591 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 6 Feb 2020 14:26:38 -0800 Subject: [PATCH 17/19] Reduce the number of lookups in hash_insert! by folding the contains_key and get_mut calls into one --- src/lib/xmlparse.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index a0c92ad..3997754 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -988,16 +988,20 @@ macro_rules! hash_insert { ($map:expr, $key:expr, $et:ident) => {{ let __key = $key; let __hk = HashKey::from(__key); - if !$map.contains_key(&__hk) { - if $map.try_reserve(1).is_ok() { + $map.get_mut(&__hk) + .map(|x| x.as_mut() as *mut $et) + .unwrap_or_else(|| { + if $map.try_reserve(1).is_err() { + return ptr::null_mut(); + } + let v = $et { name: __key, ..std::mem::zeroed() }; if let Ok(b) = Box::try_new(v) { - $map.insert(__hk.clone(), b); + $map.entry(__hk).or_insert(b).as_mut() as *mut $et + } else { + ptr::null_mut() } - } - } - $map.get_mut(&__hk) - .map_or_else(std::ptr::null_mut, |x| x.as_mut()) + }) }}; } From 19bceead70af166533d2b7f4bbe705253f6b4fac Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 6 Feb 2020 16:41:57 -0800 Subject: [PATCH 18/19] Revert "Remove OldEncoding structure" This reverts commit 32a224815fe44ac2ebb5f3ade3da4a5389f43fcf. --- src/lib/xmlparse.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 3997754..38ebc3f 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -398,6 +398,13 @@ pub enum EncodingType { Internal, } +pub enum OldEncoding { + Global(&'static dyn XmlEncoding), + Init(Box), + Unknown(Box), + Internal(&'static dyn XmlEncoding), +} + impl EncodingType { fn is_internal(&self) -> bool { match self { From 6336948f14ba93e1fb26453607821a185837a19e Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 6 Feb 2020 16:42:58 -0800 Subject: [PATCH 19/19] Revert "Revert "Remove OldEncoding structure"" This reverts commit 19bceead70af166533d2b7f4bbe705253f6b4fac. --- src/lib/xmlparse.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib/xmlparse.rs b/src/lib/xmlparse.rs index 38ebc3f..3997754 100644 --- a/src/lib/xmlparse.rs +++ b/src/lib/xmlparse.rs @@ -398,13 +398,6 @@ pub enum EncodingType { Internal, } -pub enum OldEncoding { - Global(&'static dyn XmlEncoding), - Init(Box), - Unknown(Box), - Internal(&'static dyn XmlEncoding), -} - impl EncodingType { fn is_internal(&self) -> bool { match self {