From 1080e515282fd58385fe6d8d5884bded84ac981b Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 1 Jun 2026 10:19:33 -0400 Subject: [PATCH 01/58] Starting mimalloc integration with libresolve. This commit contains modifications to the Dockerfile and cargo files to ensure mimalloc source is correctly linked with libresolve. --- Dockerfile | 13 +++++++++++ resolve-cveassert/libresolve/Cargo.lock | 23 +++++++++++++++++++ resolve-cveassert/libresolve/Cargo.toml | 2 ++ resolve-cveassert/libresolve/src/build.rs | 6 +++++ resolve-cveassert/libresolve/src/remediate.rs | 14 +++++++++++ 5 files changed, 58 insertions(+) create mode 100644 resolve-cveassert/libresolve/src/build.rs diff --git a/Dockerfile b/Dockerfile index 60c3d6df3..84a023849 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,6 +63,19 @@ COPY resolve-cli /resolve/resolve-cli COPY Makefile /resolve/Makefile COPY CMakeLists.txt /resolve/CMakeLists.txt +# Build/Install mimalloc +ARG MIMALLOC_REPO_URL="https://github.com/microsoft/mimalloc" +ARG MIMALLOC_VERSION="v3.3.2" +RUN git clone --depth 1 --branch "${MIMALLOC_VERSION}" "${MIMALLOC_REPO_URL}" \ + && cd /mimalloc \ + && mkdir -p build \ + && cd build \ + && cmake .. \ + -DMI_BUILD_SHARED=OFF \ + -DMI_BUILD_STATIC=ON \ + -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ + && make + # Build WORKDIR /resolve/ RUN PATH=$PATH:~/.cargo/bin make build-release install diff --git a/resolve-cveassert/libresolve/Cargo.lock b/resolve-cveassert/libresolve/Cargo.lock index 7c237a0bc..bd01d043a 100644 --- a/resolve-cveassert/libresolve/Cargo.lock +++ b/resolve-cveassert/libresolve/Cargo.lock @@ -73,6 +73,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cc" +version = "1.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -102,6 +112,12 @@ dependencies = [ "log", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -263,6 +279,7 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" name = "resolve" version = "0.1.0" dependencies = [ + "cc", "env_logger", "libc", "log", @@ -301,6 +318,12 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "syn" version = "2.0.111" diff --git a/resolve-cveassert/libresolve/Cargo.toml b/resolve-cveassert/libresolve/Cargo.toml index 47c09c4b2..fd810394a 100644 --- a/resolve-cveassert/libresolve/Cargo.toml +++ b/resolve-cveassert/libresolve/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "resolve" +build = "src/build.rs" version = "0.1.0" edition = "2024" @@ -7,6 +8,7 @@ edition = "2024" crate-type = ["cdylib"] [dependencies] +cc = "1.2.63" env_logger = "0.11.8" libc = "0.2.174" log = "0.4.29" diff --git a/resolve-cveassert/libresolve/src/build.rs b/resolve-cveassert/libresolve/src/build.rs new file mode 100644 index 000000000..b7fa313fb --- /dev/null +++ b/resolve-cveassert/libresolve/src/build.rs @@ -0,0 +1,6 @@ +fn main() { + println!("cargo:warning=LINKING_MIMALLOC_ARCHIVE"); + // TODO: Fill in this with the correct path + println!("cargo:rustc-link-search=native=/mimalloc/build"); + println!("cargo:rustc-link-lib=static=mimalloc"); +} diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 759f2fb73..4a0c5c317 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -13,6 +13,20 @@ use crate::shadowobjs::{ use log::{info, warn}; use std::ffi::CStr; + +#[link(name = "mimalloc")] +unsafe extern "C" { + fn mi_malloc(size: usize) -> *mut c_void; +} + +#[unsafe(no_mangle)] +pub extern "C" fn test_mi() { + unsafe { + let p = mi_malloc(16); + let _ = p; + } +} + /** * @brief - Registers stack allocations in shadow memory * @input From d832fb60f55641f2c2ed213dddba9cf87b03e455 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 1 Jun 2026 14:09:56 -0400 Subject: [PATCH 02/58] Dockerfile: Removed mimalloc build from dockerfile. --- Dockerfile | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 84a023849..60c3d6df3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,19 +63,6 @@ COPY resolve-cli /resolve/resolve-cli COPY Makefile /resolve/Makefile COPY CMakeLists.txt /resolve/CMakeLists.txt -# Build/Install mimalloc -ARG MIMALLOC_REPO_URL="https://github.com/microsoft/mimalloc" -ARG MIMALLOC_VERSION="v3.3.2" -RUN git clone --depth 1 --branch "${MIMALLOC_VERSION}" "${MIMALLOC_REPO_URL}" \ - && cd /mimalloc \ - && mkdir -p build \ - && cd build \ - && cmake .. \ - -DMI_BUILD_SHARED=OFF \ - -DMI_BUILD_STATIC=ON \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - && make - # Build WORKDIR /resolve/ RUN PATH=$PATH:~/.cargo/bin make build-release install From afdb2ceea3d46122222f7cd83c15fb493f3d15bc Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 1 Jun 2026 14:10:52 -0400 Subject: [PATCH 03/58] WIP: Moved mimalloc build into CMake workflow. I will make sure to document workflow and after CI run. --- resolve-cveassert/libresolve/CMakeLists.txt | 31 ++++++++++++- .../libresolve/mimalloc_shadow.c | 26 +++++++++++ resolve-cveassert/libresolve/src/build.rs | 8 ++-- resolve-cveassert/libresolve/src/remediate.rs | 45 +++++++++++++------ 4 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 resolve-cveassert/libresolve/mimalloc_shadow.c diff --git a/resolve-cveassert/libresolve/CMakeLists.txt b/resolve-cveassert/libresolve/CMakeLists.txt index 53baf51ed..2ba5dc25a 100644 --- a/resolve-cveassert/libresolve/CMakeLists.txt +++ b/resolve-cveassert/libresolve/CMakeLists.txt @@ -3,6 +3,29 @@ include(GNUInstallDirs) include(ExternalProject) +include(FetchContent) + +# ### Pulling and building mimalloc project +FetchContent_Declare( + mimalloc + GIT_REPOSITORY https://github.com/microsoft/mimalloc.git + GIT_TAG v3.3.2 +) + +# # Force static build +set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE) +set(MI_BUILD_STATIC ON CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(mimalloc) + +target_sources(mimalloc-static PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc_shadow.c +) +set(MIMALLOC_LIB_DIR ${mimalloc_BINARY_DIR}) + +set_target_properties(mimalloc-static PROPERTIES + POSITION_INDEPENDENT_CODE ON +) # Map CMake build type to Cargo flags if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "") @@ -24,10 +47,13 @@ file(GLOB_RECURSE RUST_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/sr add_custom_command( OUTPUT ${RUST_LIB} COMMAND - ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${RUST_OUT_DIR} cargo build ${CARGO_FLAGS} + ${CMAKE_COMMAND} -E env + CARGO_TARGET_DIR=${RUST_OUT_DIR} + MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR} + cargo build ${CARGO_FLAGS} WORKING_DIRECTORY ${RUST_CRATE_DIR} COMMENT "Building libresolve.so" VERBATIM - DEPENDS ${RUST_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.lock ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml ${CMAKE_CURRENT_SOURCE_DIR}/rust-toolchain.toml + DEPENDS mimalloc-static ${RUST_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.lock ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml ${CMAKE_CURRENT_SOURCE_DIR}/rust-toolchain.toml ) add_custom_target(test-libresolve @@ -37,4 +63,5 @@ add_custom_target(test-libresolve ) add_custom_target(libresolve ALL DEPENDS ${RUST_LIB}) +add_dependencies(libresolve mimalloc-static) install(FILES ${RUST_LIB} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c new file mode 100644 index 000000000..16c97841a --- /dev/null +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -0,0 +1,26 @@ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include +#include + +typedef struct { + uint64_t page_id; + size_t block_index; + void *page_start; +} resolve_info_t; + +resolve_info_t mi_resolve_ptr(void *p) { + mi_page_t *page = _mi_ptr_page(p); + + resolve_info_t info; + + info.page_start = mi_page_start(p); + info.page_id = (uint64_t)(uintptr_t)page; + + size_t block_size = page->block_size; + uintptr_t offset = (uintptr_t)p - (uintptr_t)info.page_start; + + info.block_index = offset / block_size; + + return info; +} diff --git a/resolve-cveassert/libresolve/src/build.rs b/resolve-cveassert/libresolve/src/build.rs index b7fa313fb..ee879105b 100644 --- a/resolve-cveassert/libresolve/src/build.rs +++ b/resolve-cveassert/libresolve/src/build.rs @@ -1,6 +1,6 @@ fn main() { - println!("cargo:warning=LINKING_MIMALLOC_ARCHIVE"); - // TODO: Fill in this with the correct path - println!("cargo:rustc-link-search=native=/mimalloc/build"); - println!("cargo:rustc-link-lib=static=mimalloc"); + let dir = std::env::var("MIMALLOC_LIB_DIR").unwrap(); + println!("cargo::warning=LINKING_MIMALLOC_ARCHIVE"); + println!("cargo::rustc-link-search=native={}", dir); + println!("cargo::rustc-link-lib=static=mimalloc"); } diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 4a0c5c317..1a90e5a44 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -11,20 +11,23 @@ use crate::shadowobjs::{ }; use log::{info, warn}; -use std::ffi::CStr; +#[repr(C)] +struct ResolveInfo { + page_id: u64, + block_size: usize, + page_start: *mut c_void, +} + #[link(name = "mimalloc")] unsafe extern "C" { fn mi_malloc(size: usize) -> *mut c_void; -} + fn mi_calloc(size: usize, count: usize) -> *mut c_void; + fn mi_realloc(ptr: *mut c_void, size: usize) -> *mut c_void; + fn mi_free(ptr: *mut c_void); -#[unsafe(no_mangle)] -pub extern "C" fn test_mi() { - unsafe { - let p = mi_malloc(16); - let _ = p; - } + fn mi_resolve_ptr(ptr: *mut c_void) -> ResolveInfo; } /** @@ -79,7 +82,7 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { - let ptr = unsafe { malloc(size + 1) }; + let ptr = unsafe { mi_malloc(size + 1) }; if ptr.is_null() { return ptr; @@ -141,7 +144,7 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { freed_guard.add_shadow_object(AllocType::Unallocated, ptr as Vaddr, obj_size.unwrap_or(0)); } - let _ = unsafe { free(ptr) }; + let _ = unsafe { mi_free(ptr) }; } /** @@ -161,7 +164,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi // Consideration: Pointer passed in may be invalidated so we need a mechanism // to remove the shadow object for the orignal allocation - let realloc_ptr = unsafe { realloc(ptr, size + 1) }; + let realloc_ptr = unsafe { mi_realloc(ptr, size + 1) }; if realloc_ptr.is_null() { return realloc_ptr; @@ -191,9 +194,9 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi * requested size */ #[unsafe(no_mangle)] -pub extern "C" fn __resolve_calloc(nelems: usize, elsize: usize) -> *mut c_void { - let ptr = unsafe { calloc(nelems, elsize) }; - let size = nelems * elsize; +pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_void { + let ptr = unsafe { mi_calloc(n_items, item_size) }; + let size = n_items * item_size; if ptr.is_null() { return ptr; @@ -536,4 +539,18 @@ mod tests { assert!(obj.is_none()); } } + + #[test] + fn test_mi_malloc_page() { + resolve_init(); + unsafe { + let ptr = __resolve_malloc(128); + let info = mi_resolve_ptr(ptr); + println!("ptr = {:p}", p); + println!("page_id = {}", info.page_id); + println!("block_idx = {}", info.block_index); + println!("page_start = {:p}", info.page_start); + __resolve_free(ptr); + } + } } From d536af55366b1301b6eb8661dcba9e909f24bdc4 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 1 Jun 2026 15:18:50 -0400 Subject: [PATCH 04/58] CMakeLists.txt: Fixed CMake file to correctly pass path to static mimalloc archive to cargo so that downstream tests pass. --- resolve-cveassert/libresolve/CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/resolve-cveassert/libresolve/CMakeLists.txt b/resolve-cveassert/libresolve/CMakeLists.txt index 2ba5dc25a..ba5df5f55 100644 --- a/resolve-cveassert/libresolve/CMakeLists.txt +++ b/resolve-cveassert/libresolve/CMakeLists.txt @@ -5,24 +5,28 @@ include(GNUInstallDirs) include(ExternalProject) include(FetchContent) -# ### Pulling and building mimalloc project +#### Fetching and building mimalloc project FetchContent_Declare( mimalloc GIT_REPOSITORY https://github.com/microsoft/mimalloc.git GIT_TAG v3.3.2 ) -# # Force static build +## Force static build set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE) set(MI_BUILD_STATIC ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(mimalloc) +# Add the shim source to the mimalloc proj target_sources(mimalloc-static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc_shadow.c ) + set(MIMALLOC_LIB_DIR ${mimalloc_BINARY_DIR}) +message(STATUS "MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR}") +## mimalloc proj must be PIC to ensure compatibility with libresolve set_target_properties(mimalloc-static PROPERTIES POSITION_INDEPENDENT_CODE ON ) @@ -49,7 +53,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${RUST_OUT_DIR} - MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR} + MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR} # pass the static mimalloc path cargo build ${CARGO_FLAGS} WORKING_DIRECTORY ${RUST_CRATE_DIR} COMMENT "Building libresolve.so" VERBATIM @@ -57,7 +61,10 @@ add_custom_command( ) add_custom_target(test-libresolve - COMMAND cargo test + COMMAND + ${CMAKE_COMMAND} -E env + MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR} # Note: Pass the static mimalloc loc so that build.rs does not panic + cargo test WORKING_DIRECTORY ${RUST_CRATE_DIR} COMMENT "Running regression tests for libresolve" ) From 346a4d81a32460f8ee22c91fc97f61149be1ab0d Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 1 Jun 2026 15:19:26 -0400 Subject: [PATCH 05/58] remediate.rs: Fixed test but we need to test this on a small file to see if it works correctly. --- resolve-cveassert/libresolve/src/remediate.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 1a90e5a44..28799cacf 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -16,17 +16,19 @@ use log::{info, warn}; #[repr(C)] struct ResolveInfo { page_id: u64, - block_size: usize, + block_index: usize, page_start: *mut c_void, } #[link(name = "mimalloc")] -unsafe extern "C" { +unsafe extern "C" { + // Allocator API fn mi_malloc(size: usize) -> *mut c_void; fn mi_calloc(size: usize, count: usize) -> *mut c_void; fn mi_realloc(ptr: *mut c_void, size: usize) -> *mut c_void; fn mi_free(ptr: *mut c_void); - + + // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> ResolveInfo; } @@ -544,9 +546,9 @@ mod tests { fn test_mi_malloc_page() { resolve_init(); unsafe { - let ptr = __resolve_malloc(128); + let ptr = __resolve_malloc(0x10); let info = mi_resolve_ptr(ptr); - println!("ptr = {:p}", p); + println!("ptr = {:p}", ptr); println!("page_id = {}", info.page_id); println!("block_idx = {}", info.block_index); println!("page_start = {:p}", info.page_start); From 7c8081f1977bab2d8bab24105857426907e14c43 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 2 Jun 2026 10:18:20 -0400 Subject: [PATCH 06/58] shadowobjs.rs: Cleaned up some comments. --- resolve-cveassert/libresolve/src/shadowobjs.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/resolve-cveassert/libresolve/src/shadowobjs.rs b/resolve-cveassert/libresolve/src/shadowobjs.rs index b60862946..05f5b8c19 100644 --- a/resolve-cveassert/libresolve/src/shadowobjs.rs +++ b/resolve-cveassert/libresolve/src/shadowobjs.rs @@ -23,11 +23,8 @@ pub enum AllocType { #[derive(Debug, Clone, Copy)] pub struct ShadowObject { - /// Allocation type (Heap, Stack, Global, etc..) pub alloc_type: AllocType, - // Base address of the allocated object mapped to u64 pub base: Vaddr, - /// Last address of the allocated object pub limit: Vaddr, size: usize, } From 84cc0eb2827dcf9ca5f23ed659260c5a154a3a0f Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 4 Jun 2026 13:26:32 -0400 Subject: [PATCH 07/58] mimalloc_shadow.c: Modified shim to lookup bounds of mimalloc allocation. --- .../libresolve/mimalloc_shadow.c | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 16c97841a..d0b27cdbc 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -4,23 +4,28 @@ #include typedef struct { - uint64_t page_id; + void *base; + void *limit; + size_t block_size; size_t block_index; - void *page_start; -} resolve_info_t; +} bounds_info_t; -resolve_info_t mi_resolve_ptr(void *p) { - mi_page_t *page = _mi_ptr_page(p); - - resolve_info_t info; - info.page_start = mi_page_start(p); - info.page_id = (uint64_t)(uintptr_t)page; +bounds_info_t mi_resolve_ptr(void* p) { + mi_page_t *page = _mi_ptr_page(p); + + const size_t block_size = page->block_size; - size_t block_size = page->block_size; - uintptr_t offset = (uintptr_t)p - (uintptr_t)info.page_start; + uintptr_t page_start = (uintptr_t)page->page_start; + uintptr_t ptr = (uintptr_t)p; - info.block_index = offset / block_size; + size_t block_index = (ptr - page_start) / block_size; + uintptr_t base_addr = page_start + block_index * block_size; - return info; + bounds_info_t bounds; + bounds.base = (void*)base_addr; + bounds.limit = (void*)(base_addr + block_size); + bounds.block_size = block_size; + bounds.block_index = block_index; + return bounds; } From 9f3629097735f3a08687a06040e1fffc65468263 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 4 Jun 2026 13:27:06 -0400 Subject: [PATCH 08/58] WIP: Testing bounds-checking with mimalloc. --- resolve-cveassert/libresolve/src/remediate.rs | 142 +++++++++--------- 1 file changed, 67 insertions(+), 75 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 28799cacf..970da9979 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -12,12 +12,12 @@ use crate::shadowobjs::{ use log::{info, warn}; - #[repr(C)] -struct ResolveInfo { - page_id: u64, +struct BoundsInfo { + base: *mut c_void, + limit: *mut c_void, + block_size: usize, block_index: usize, - page_start: *mut c_void, } #[link(name = "mimalloc")] @@ -26,10 +26,12 @@ unsafe extern "C" { fn mi_malloc(size: usize) -> *mut c_void; fn mi_calloc(size: usize, count: usize) -> *mut c_void; fn mi_realloc(ptr: *mut c_void, size: usize) -> *mut c_void; + fn mi_strdup(ptr: *mut c_char) -> *mut c_char; + fn mi_strndup(ptr: *mut c_char, size: usize) -> *mut c_char; fn mi_free(ptr: *mut c_void); // Shim API - fn mi_resolve_ptr(ptr: *mut c_void) -> ResolveInfo; + fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; } /** @@ -85,6 +87,7 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { let ptr = unsafe { mi_malloc(size + 1) }; + let bounds_info = unsafe { mi_resolve_ptr(ptr) }; if ptr.is_null() { return ptr; @@ -100,6 +103,9 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr, size ); + info!("[RESOLVE] bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); + info!("[RESOLVE] block index: {}", bounds_info.block_index); + info!("[RESOLVE] block size: {}", bounds_info.block_size); ptr } @@ -146,9 +152,9 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { freed_guard.add_shadow_object(AllocType::Unallocated, ptr as Vaddr, obj_size.unwrap_or(0)); } - let _ = unsafe { mi_free(ptr) }; + let _ = unsafe { mi_free(ptr) }; } - +// /** * @brief - RESOLVE wrapper for libc realloc * @input @@ -226,7 +232,7 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { - let string_ptr = unsafe { strdup(ptr) }; + let string_ptr = unsafe { mi_strdup(ptr) }; if string_ptr.is_null() { return string_ptr; @@ -260,7 +266,7 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_char { - let string_ptr = unsafe { strndup(ptr, size + 1) }; + let string_ptr = unsafe { mi_strndup(ptr, size + 1) }; if string_ptr.is_null() { return string_ptr; @@ -459,21 +465,21 @@ pub extern "C" fn __resolve_get_bounds(ptr: *mut c_void) -> ShadowObjBounds { sobj } - -#[unsafe(no_mangle)] -pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { - let base = base_ptr as Vaddr; - - let find_in = |table: &crate::MutexWrap| { - let t = table.lock(); - t.search_intersection(base).map(|o| o.alloc_type) - }; - - // Why does this search freed before alive? - let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); - - alloc_type.unwrap_or(AllocType::Unknown) -} +// +//#[unsafe(no_mangle)] +//pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { +// let base = base_ptr as Vaddr; +// +// let find_in = |table: &crate::MutexWrap| { +// let t = table.lock(); +// t.search_intersection(base).map(|o| o.alloc_type) +// }; +// +// // Why does this search freed before alive? +// let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); +// +// alloc_type.unwrap_or(AllocType::Unknown) +//} /** * @brief - Logs invalid memory access for a given function @@ -504,55 +510,41 @@ mod tests { use crate::file::resolve_init; use crate::shadowobjs::AllocType; - #[test] - fn test_malloc_free() { - resolve_init(); - // Allocation should successfully return a memory block - let ptr = __resolve_malloc(0x10); - assert!(!ptr.is_null()); - - // We should track the obj correctly - { - let table = ALIVE_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_some()); - let obj = obj.unwrap(); - assert!(obj.size() == 0x10); - assert!(obj.base == ptr as Vaddr); - assert!(obj.alloc_type == AllocType::Heap); - } - - __resolve_free(ptr); - - // After freeing a block we should track that it has been freed - { - let table = FREED_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_some()); - } - - // And it should no longer be in the alive obj list. - { - let table = ALIVE_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_none()); - } - } - - #[test] - fn test_mi_malloc_page() { - resolve_init(); - unsafe { - let ptr = __resolve_malloc(0x10); - let info = mi_resolve_ptr(ptr); - println!("ptr = {:p}", ptr); - println!("page_id = {}", info.page_id); - println!("block_idx = {}", info.block_index); - println!("page_start = {:p}", info.page_start); - __resolve_free(ptr); - } - } + #[test] + fn test_malloc_free() { + resolve_init(); + // Allocation should successfully return a memory block + let ptr = __resolve_malloc(0x10); + assert!(!ptr.is_null()); + + // We should track the obj correctly + { + let table = ALIVE_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_some()); + let obj = obj.unwrap(); + assert!(obj.size() == 0x10); + assert!(obj.base == ptr as Vaddr); + assert!(obj.alloc_type == AllocType::Heap); + } + + __resolve_free(ptr); + + // After freeing a block we should track that it has been freed + { + let table = FREED_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_some()); + } + + // And it should no longer be in the alive obj list. + { + let table = ALIVE_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_none()); + } + } } From 8091093b202253d151e53c065d4a83f43cdcd95e Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 5 Jun 2026 10:48:56 -0400 Subject: [PATCH 09/58] remediate.rs: This will not pass CI tests, this is just so that I can compare the mimalloc approach to strict shadow object bounds approach. --- resolve-cveassert/libresolve/src/remediate.rs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 970da9979..da028379b 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -87,25 +87,25 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { let ptr = unsafe { mi_malloc(size + 1) }; - let bounds_info = unsafe { mi_resolve_ptr(ptr) }; + //let bounds_info = unsafe { mi_resolve_ptr(ptr) }; if ptr.is_null() { return ptr; } - { - let mut obj_list = ALIVE_OBJ_LIST.lock(); - obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); - } + //{ + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); + //} info!( "[HEAP] Registered heap object (malloc): addr={:p}, size={}", ptr, size ); - info!("[RESOLVE] bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); - info!("[RESOLVE] block index: {}", bounds_info.block_index); - info!("[RESOLVE] block size: {}", bounds_info.block_size); + //info!("[RESOLVE] bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); + //info!("[RESOLVE] block index: {}", bounds_info.block_index); + //info!("[RESOLVE] block size: {}", bounds_info.block_size); ptr } @@ -152,7 +152,7 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { freed_guard.add_shadow_object(AllocType::Unallocated, ptr as Vaddr, obj_size.unwrap_or(0)); } - let _ = unsafe { mi_free(ptr) }; + let _ = unsafe { mi_free(ptr) }; } // /** @@ -190,7 +190,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi realloc_ptr, size ); - realloc_ptr + realloc_ptr } /** @@ -210,10 +210,10 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v return ptr; } - { - let mut obj_list = ALIVE_OBJ_LIST.lock(); - obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); - } + //{ + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); + //} info!( "[HEAP] Registered heap object (calloc): addr={:p}, size={}", @@ -241,11 +241,11 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { // +1 to include null termination byte. We should allow program to read this value. // Otherwise how would the program find the end of the string? // Although writing it to something else is probably a bad idea, this too should be allowed. - let sizeofstr = unsafe { strlen(ptr) + 1 }; - { - let mut obj_list = ALIVE_OBJ_LIST.lock(); - obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); - } + // let sizeofstr = unsafe { strlen(ptr) + 1 }; + // { + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); + // } info!( "[HEAP] Registered heap object (strdup): addr={:p}, size={}", @@ -276,12 +276,12 @@ pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_cha // We don't actually know how much memory the libc will allocate, but // strnlen(ptr, size) + 1 is a safe lower bound. // strlen(string_ptr) + 1 would also be valid I think. - let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; + //let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; - { - let mut obj_list = ALIVE_OBJ_LIST.lock(); - obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); - } + //{ + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); + //} info!( "[HEAP] Registered heap object (strndup): addr={:p}, size={}", From e50c2a6215eb57b58337112548217b4e9b147ffb Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 8 Jun 2026 11:43:06 -0400 Subject: [PATCH 10/58] remediate.rs: Adding wrapper for getline function. Testing with challenge problem. --- resolve-cveassert/libresolve/src/remediate.rs | 61 +++++++++++++++++-- .../src/InstrumentAllocators.cpp | 3 + 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index da028379b..2df3bb789 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -71,12 +71,65 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize SHADOW_STACK.with_borrow_mut(|ss| ss.invalidate_at(base, size)); - info!( - "[STACK] Unregistered stack object: addr={:p}, size={}", - ptr, size - ); + info!("[STACK] Free addr 0x{base:x} size {size}"); +} + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, stream: *mut FILE) -> ssize_t { + if line.is_null() || size.is_null() || stream.is_null() { + return -1; + } + + unsafe { + if (*line).is_null() || *size == 0 { + *size = 128; + *line = __resolve_malloc(*size + 1) as *mut c_char; + + // check if the pointer is null + if (*line).is_null() { return -1; } + } + + let mut pos: size_t = 0; + let mut c: c_int; + + loop { + c = fgetc(stream); + if c == EOF { break; } + + if pos + 1 >= *size { // Expand buffer + let new_size = *size * 2; + let new_ptr = __resolve_realloc(*line as *mut c_void, new_size); + + if new_ptr.is_null() { + return -1; + } + + *line = new_ptr as *mut c_char; + *size = new_size; + } + + // (*lineptr)[pos++] = (char)c; + (*line).add(pos).write(c as c_char); + pos += 1; + + if c == b'\n' as c_int { + break; + } + + } + + if pos == 0 && c == EOF { // No data read + return -1; + } + + (*line).add(pos).write(0); // (*lineptr)[pos] = '\0' + } + + pos as ssize_t } + + /** * @brief - RESOLVE wrapper for libc malloc * @input diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index dfd9b4b62..3d7684961 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -85,6 +85,9 @@ void instrumentLibraryAllocations(Function *F) { false)); wrapLibraryFunction( F, "munmap", FunctionType::get(integerType, {ptrType, sizeType}, false)); + wrapLibraryFunction( + F, "getline", + FunctionType::get(size_ty, {ptr_ty, ptr_ty, ptr_ty}, false)); } void instrumentAlloca(Function *F) { From 62148ec1477c1070c44999a18f899c1dd546ea43 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 8 Jun 2026 11:53:12 -0400 Subject: [PATCH 11/58] remediate.rs: Fixing Rust errors. --- resolve-cveassert/libresolve/src/remediate.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 2df3bb789..99b16850c 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -123,9 +123,8 @@ pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, s } (*line).add(pos).write(0); // (*lineptr)[pos] = '\0' + pos as ssize_t } - - pos as ssize_t } From 12557f0abb96253834e0c942904df59979098294 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 8 Jun 2026 12:01:13 -0400 Subject: [PATCH 12/58] remediate.rs: Removed the plus one and using resolve wrapped malloc and realloc. --- resolve-cveassert/libresolve/src/remediate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 99b16850c..6bba0225d 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -83,7 +83,7 @@ pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, s unsafe { if (*line).is_null() || *size == 0 { *size = 128; - *line = __resolve_malloc(*size + 1) as *mut c_char; + *line = __resolve_malloc(*size) as *mut c_char; // check if the pointer is null if (*line).is_null() { return -1; } From 1835171c316aba6a233199e47290c9703e97951f Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 8 Jun 2026 14:29:05 -0400 Subject: [PATCH 13/58] remediate.rs: Added resolve wrapper for getdelim function. --- resolve-cveassert/libresolve/src/remediate.rs | 20 +++++++++---------- .../src/InstrumentAllocators.cpp | 3 +++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 6bba0225d..1c5e1c133 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -75,18 +75,18 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize } #[unsafe(no_mangle)] -pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, stream: *mut FILE) -> ssize_t { - if line.is_null() || size.is_null() || stream.is_null() { +pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t, stream: *mut FILE) -> ssize_t { + if lineptr.is_null() || size.is_null() || stream.is_null() { return -1; } unsafe { - if (*line).is_null() || *size == 0 { + if (*lineptr).is_null() || *size == 0 { *size = 128; - *line = __resolve_malloc(*size) as *mut c_char; + *lineptr = __resolve_malloc(*size) as *mut c_char; // check if the pointer is null - if (*line).is_null() { return -1; } + if (*lineptr).is_null() { return -1; } } let mut pos: size_t = 0; @@ -98,18 +98,18 @@ pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, s if pos + 1 >= *size { // Expand buffer let new_size = *size * 2; - let new_ptr = __resolve_realloc(*line as *mut c_void, new_size); + let new_buf = __resolve_realloc(*lineptr as *mut c_void, new_size); - if new_ptr.is_null() { + if new_buf.is_null() { return -1; } - *line = new_ptr as *mut c_char; + *lineptr = new_buf as *mut c_char; *size = new_size; } // (*lineptr)[pos++] = (char)c; - (*line).add(pos).write(c as c_char); + (*lineptr).add(pos).write(c as c_char); pos += 1; if c == b'\n' as c_int { @@ -122,7 +122,7 @@ pub extern "C" fn __resolve_getline(line: *mut *mut c_char, size: *mut size_t, s return -1; } - (*line).add(pos).write(0); // (*lineptr)[pos] = '\0' + (*lineptr).add(pos).write(0); // (*lineptr)[pos] = '\0' pos as ssize_t } } diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index 3d7684961..8154d04ec 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -88,6 +88,9 @@ void instrumentLibraryAllocations(Function *F) { wrapLibraryFunction( F, "getline", FunctionType::get(size_ty, {ptr_ty, ptr_ty, ptr_ty}, false)); + wrapLibraryFunction( + F, "getdelim", + FunctionType::get(size_ty, {ptr_ty, ptr_ty, size_ty, ptr_ty}, false)); } void instrumentAlloca(Function *F) { From dcf05486a83e19e08538a523b4de6ee616fa1144 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 9 Jun 2026 08:36:15 -0400 Subject: [PATCH 14/58] remediate.rs: WIP debugging foreign allocation that occurs in dependency. Added debugging statement and logic to use libc free if the allocation is not from mimalloc. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 6 ++++++ resolve-cveassert/libresolve/src/remediate.rs | 1 + 2 files changed, 7 insertions(+) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index d0b27cdbc..0d9c1ee4c 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -29,3 +29,9 @@ bounds_info_t mi_resolve_ptr(void* p) { bounds.block_index = block_index; return bounds; } + +bool mi_is_heap_owned(const void* p) { + return mi_check_owned(p); +} + + diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 1c5e1c133..93bd08e5e 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -32,6 +32,7 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; + fn mi_is_heap_owned(ptr: *mut c_void) -> bool; } /** From 2f0527024a8071b50a1a75218bd778a058003f36 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 11:18:36 -0400 Subject: [PATCH 15/58] remediate.rs: Make sure all logging is commented out for poller testing. --- resolve-cveassert/libresolve/src/remediate.rs | 108 +++++++++--------- .../libresolve/src/shadowobjs.rs | 71 +++++++----- 2 files changed, 94 insertions(+), 85 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 93bd08e5e..cec9f495d 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -156,9 +156,9 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr, size ); - //info!("[RESOLVE] bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); - //info!("[RESOLVE] block index: {}", bounds_info.block_index); - //info!("[RESOLVE] block size: {}", bounds_info.block_size); + info!("[RESOLVE] block bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); + info!("[RESOLVE] block index: {}", bounds_info.block_index); + info!("[RESOLVE] block size: {}", bounds_info.block_size); ptr } @@ -259,22 +259,22 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v let ptr = unsafe { mi_calloc(n_items, item_size) }; let size = n_items * item_size; - if ptr.is_null() { - return ptr; - } +// if ptr.is_null() { +// return ptr; +// } - //{ - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); - //} +// { +// let mut obj_list = ALIVE_OBJ_LIST.lock(); +// obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); +// } info!( "[HEAP] Registered heap object (calloc): addr={:p}, size={}", ptr, size ); - ptr -} +// ptr +// } /** * @brief - RESOLVE wrapper for libc strdup @@ -287,26 +287,26 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { let string_ptr = unsafe { mi_strdup(ptr) }; - if string_ptr.is_null() { - return string_ptr; - } +// if string_ptr.is_null() { +// return string_ptr; +// } - // +1 to include null termination byte. We should allow program to read this value. - // Otherwise how would the program find the end of the string? - // Although writing it to something else is probably a bad idea, this too should be allowed. - // let sizeofstr = unsafe { strlen(ptr) + 1 }; - // { - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); - // } +// // +1 to include null termination byte. We should allow program to read this value. +// // Otherwise how would the program find the end of the string? +// // Although writing it to something else is probably a bad idea, this too should be allowed. +// let sizeofstr = unsafe { strlen(ptr) + 1 }; +// { +// let mut obj_list = ALIVE_OBJ_LIST.lock(); +// obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); +// } info!( "[HEAP] Registered heap object (strdup): addr={:p}, size={}", string_ptr, sizeofstr ); - string_ptr -} +// string_ptr +// } /** * @brief - RESOLVE wrapper for libc strndup @@ -321,28 +321,28 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_char { let string_ptr = unsafe { mi_strndup(ptr, size + 1) }; - if string_ptr.is_null() { - return string_ptr; - } +// if string_ptr.is_null() { +// return string_ptr; +// } - // +1 to include null termination byte. We should allow program to read this value. - // We don't actually know how much memory the libc will allocate, but - // strnlen(ptr, size) + 1 is a safe lower bound. - // strlen(string_ptr) + 1 would also be valid I think. - //let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; +// // +1 to include null termination byte. We should allow program to read this value. +// // We don't actually know how much memory the libc will allocate, but +// // strnlen(ptr, size) + 1 is a safe lower bound. +// // strlen(string_ptr) + 1 would also be valid I think. +// let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; - //{ - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); - //} +// { +// let mut obj_list = ALIVE_OBJ_LIST.lock(); +// obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); +// } info!( "[HEAP] Registered heap object (strndup): addr={:p}, size={}", string_ptr, sizeofstr ); - string_ptr -} +// string_ptr +// } /** * @brief - RESOLVE wrapper for libc mmap @@ -518,21 +518,21 @@ pub extern "C" fn __resolve_get_bounds(ptr: *mut c_void) -> ShadowObjBounds { sobj } -// -//#[unsafe(no_mangle)] -//pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { -// let base = base_ptr as Vaddr; -// -// let find_in = |table: &crate::MutexWrap| { -// let t = table.lock(); -// t.search_intersection(base).map(|o| o.alloc_type) -// }; -// -// // Why does this search freed before alive? -// let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); -// -// alloc_type.unwrap_or(AllocType::Unknown) -//} + +#[unsafe(no_mangle)] +pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { + let base = base_ptr as Vaddr; + + let find_in = |table: &crate::MutexWrap| { + let t = table.lock(); + t.search_intersection(base).map(|o| o.alloc_type) + }; + + // Why does this search freed before alive? + let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); + + alloc_type.unwrap_or(AllocType::Unknown) +} /** * @brief - Logs invalid memory access for a given function diff --git a/resolve-cveassert/libresolve/src/shadowobjs.rs b/resolve-cveassert/libresolve/src/shadowobjs.rs index 05f5b8c19..19e8ccf4e 100644 --- a/resolve-cveassert/libresolve/src/shadowobjs.rs +++ b/resolve-cveassert/libresolve/src/shadowobjs.rs @@ -391,9 +391,10 @@ mod tests { table.add_shadow_object(AllocType::Heap, 0x1000, 8); table.add_shadow_object(AllocType::Stack, 0x2000, 16); - //table.print_shadow_obj(); - } +// //table.print_shadow_obj(); +// } +<<<<<<< HEAD #[test] fn test_remove_shadow_objects() { let mut table = ShadowObjectTable::new(); @@ -402,21 +403,29 @@ mod tests { table.invalidate_at(0x1000); assert_eq!(table.table.len(), 1); } - - #[test] - fn test_search_intersection_found() { - let mut table = ShadowObjectTable::new(); - table.add_shadow_object(AllocType::Global, 0x3000, 4); - - let result = table.search_intersection(0x3002); - assert!(result.is_some()); - assert_eq!(result.unwrap().alloc_type, AllocType::Global); - } - - #[test] - fn test_search_intersection_not_found() { - let mut table = ShadowObjectTable::new(); - table.add_shadow_object(AllocType::Heap, 0x4000, 4); +======= +// #[test] +// fn test_remove_shadow_objects() { +// let mut table = ShadowObjectTable::new(); +// table.add_shadow_object(AllocType::Heap, 0x1000, 8); +// table.add_shadow_object(AllocType::Stack, 0x2000, 16); +// } +>>>>>>> ec6b0f1 (remediate.rs: Make sure all logging is commented out for poller testing.) + +// #[test] +// fn test_search_intersection_found() { +// let mut table = ShadowObjectTable::new(); +// table.add_shadow_object(AllocType::Global, 0x3000, 4); + +// let result = table.search_intersection(0x3002); +// assert!(result.is_some()); +// assert_eq!(result.unwrap().alloc_type, AllocType::Global); +// } + +// #[test] +// fn test_search_intersection_not_found() { +// let mut table = ShadowObjectTable::new(); +// table.add_shadow_object(AllocType::Heap, 0x4000, 4); let result = table.search_intersection(0x5000); assert!(result.is_none()); @@ -442,22 +451,22 @@ mod tests { GLOBALS.lock().clear(); } - #[test] - fn test_is_allocation() { - let mut table = ShadowObjectTable::new(); - table.add_shadow_object(AllocType::Stack, 0x6000, 8); +// #[test] +// fn test_is_allocation() { +// let mut table = ShadowObjectTable::new(); +// table.add_shadow_object(AllocType::Stack, 0x6000, 8); - let typ = table.search_intersection(0x6004).unwrap().alloc_type; - assert_eq!(typ, AllocType::Stack); - } - #[test] - fn bounds_testing() { - let mut table = ShadowObjectTable::new(); - table.add_shadow_object(AllocType::Heap, 0x8000, 8); +// let typ = table.search_intersection(0x6004).unwrap().alloc_type; +// assert_eq!(typ, AllocType::Stack); +// } +// #[test] +// fn bounds_testing() { +// let mut table = ShadowObjectTable::new(); +// table.add_shadow_object(AllocType::Heap, 0x8000, 8); - for x in 0x8000..0x8008 { - assert!(table.search_intersection(x).is_some()); - } +// for x in 0x8000..0x8008 { +// assert!(table.search_intersection(x).is_some()); +// } assert!(table.search_intersection(0x8009).is_none()); assert!(table.search_intersection(0x7FFF).is_none()); From 835c860d74f4cfdbe655c687564ebde931581490 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 11:19:18 -0400 Subject: [PATCH 16/58] remediate.rs: Comment out all logging. --- resolve-cveassert/libresolve/src/remediate.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index cec9f495d..efd2f0d62 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -156,9 +156,9 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr, size ); - info!("[RESOLVE] block bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); - info!("[RESOLVE] block index: {}", bounds_info.block_index); - info!("[RESOLVE] block size: {}", bounds_info.block_size); + //info!("[RESOLVE] block bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); + //info!("[RESOLVE] block index: {}", bounds_info.block_index); + //info!("[RESOLVE] block size: {}", bounds_info.block_size); ptr } From cf470f2f2e3eff9ce5414c269dcf841aab8c346e Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 11:51:10 -0400 Subject: [PATCH 17/58] remediate.rs: Restored commit 48dbed5 for testing. --- resolve-cveassert/libresolve/src/remediate.rs | 101 +++++++++--------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index efd2f0d62..f8ae65a52 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -32,7 +32,6 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; - fn mi_is_heap_owned(ptr: *mut c_void) -> bool; } /** @@ -156,7 +155,7 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr, size ); - //info!("[RESOLVE] block bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); + //info!("[RESOLVE] bounds: (0x{:x}, 0x{:x})", bounds_info.base as Vaddr, bounds_info.limit as Vaddr); //info!("[RESOLVE] block index: {}", bounds_info.block_index); //info!("[RESOLVE] block size: {}", bounds_info.block_size); ptr @@ -259,22 +258,22 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v let ptr = unsafe { mi_calloc(n_items, item_size) }; let size = n_items * item_size; -// if ptr.is_null() { -// return ptr; -// } + if ptr.is_null() { + return ptr; + } -// { -// let mut obj_list = ALIVE_OBJ_LIST.lock(); -// obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); -// } + //{ + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); + //} info!( "[HEAP] Registered heap object (calloc): addr={:p}, size={}", ptr, size ); -// ptr -// } + ptr +} /** * @brief - RESOLVE wrapper for libc strdup @@ -287,26 +286,26 @@ pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_v pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { let string_ptr = unsafe { mi_strdup(ptr) }; -// if string_ptr.is_null() { -// return string_ptr; -// } + if string_ptr.is_null() { + return string_ptr; + } -// // +1 to include null termination byte. We should allow program to read this value. -// // Otherwise how would the program find the end of the string? -// // Although writing it to something else is probably a bad idea, this too should be allowed. -// let sizeofstr = unsafe { strlen(ptr) + 1 }; -// { -// let mut obj_list = ALIVE_OBJ_LIST.lock(); -// obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); -// } + // +1 to include null termination byte. We should allow program to read this value. + // Otherwise how would the program find the end of the string? + // Although writing it to something else is probably a bad idea, this too should be allowed. + // let sizeofstr = unsafe { strlen(ptr) + 1 }; + // { + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); + // } info!( "[HEAP] Registered heap object (strdup): addr={:p}, size={}", string_ptr, sizeofstr ); -// string_ptr -// } + string_ptr +} /** * @brief - RESOLVE wrapper for libc strndup @@ -321,20 +320,20 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_char { let string_ptr = unsafe { mi_strndup(ptr, size + 1) }; -// if string_ptr.is_null() { -// return string_ptr; -// } + if string_ptr.is_null() { + return string_ptr; + } -// // +1 to include null termination byte. We should allow program to read this value. -// // We don't actually know how much memory the libc will allocate, but -// // strnlen(ptr, size) + 1 is a safe lower bound. -// // strlen(string_ptr) + 1 would also be valid I think. -// let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; + // +1 to include null termination byte. We should allow program to read this value. + // We don't actually know how much memory the libc will allocate, but + // strnlen(ptr, size) + 1 is a safe lower bound. + // strlen(string_ptr) + 1 would also be valid I think. + //let sizeofstr = unsafe { strnlen(ptr, size) + 1 }; -// { -// let mut obj_list = ALIVE_OBJ_LIST.lock(); -// obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); -// } + //{ + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); + //} info!( "[HEAP] Registered heap object (strndup): addr={:p}, size={}", @@ -518,21 +517,21 @@ pub extern "C" fn __resolve_get_bounds(ptr: *mut c_void) -> ShadowObjBounds { sobj } - -#[unsafe(no_mangle)] -pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { - let base = base_ptr as Vaddr; - - let find_in = |table: &crate::MutexWrap| { - let t = table.lock(); - t.search_intersection(base).map(|o| o.alloc_type) - }; - - // Why does this search freed before alive? - let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); - - alloc_type.unwrap_or(AllocType::Unknown) -} +// +//#[unsafe(no_mangle)] +//pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { +// let base = base_ptr as Vaddr; +// +// let find_in = |table: &crate::MutexWrap| { +// let t = table.lock(); +// t.search_intersection(base).map(|o| o.alloc_type) +// }; +// +// // Why does this search freed before alive? +// let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); +// +// alloc_type.unwrap_or(AllocType::Unknown) +//} /** * @brief - Logs invalid memory access for a given function From 765399f578283315e1fbb448f2cb6417644dc921 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 12:48:04 -0400 Subject: [PATCH 18/58] remediate.rs: Fixing remediate.rs since I lost some of the commits to git stash. --- resolve-cveassert/libresolve/src/remediate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index f8ae65a52..f71d6a51f 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -32,6 +32,7 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; + fn mi_is_heap_owned(ptr: *mut c_void) -> bool; } /** From 60c5d467fdbd26853e9abfe30f85c5e1144d3b74 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 14:07:15 -0400 Subject: [PATCH 19/58] remediate.rs: Fixing issues in compilation. --- resolve-cveassert/libresolve/src/remediate.rs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index f71d6a51f..19708fa31 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -186,6 +186,7 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { ptr as Vaddr, ); +<<<<<<< HEAD info!( "[HEAP] Unregistered heap object: addr={:p}, size={}", ptr, size @@ -197,7 +198,31 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { ptr as Vaddr ); } - } +======= + // let ptr_size = { + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // let sobj_opt = obj_list.search_intersection(ptr as Vaddr); + // let size = sobj_opt.map(|o| o.size()); + // // remove shadow obj from live list + // obj_list.invalidate_at(ptr as Vaddr); + // size + // }; + + // // Check if the shadow object exists + // match ptr_size { + // Some(size) => { + // info!( + // "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", + // ptr as Vaddr, + // ); + // } + // None => { + // warn!( + // "[FREE] No shadow object found for allocated object: 0x{:x}", + // ptr as Vaddr + // ); + // } + // } { // Insert shadow object into freed object list From c34cda58c0f3e5dabb36bba900f582dcd435890c Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 14:15:40 -0400 Subject: [PATCH 20/58] mimalloc_shadow.c: Switching to mi_is_in_heap to better handle arbitrary pointers. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 0d9c1ee4c..29ab840a4 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -31,7 +31,7 @@ bounds_info_t mi_resolve_ptr(void* p) { } bool mi_is_heap_owned(const void* p) { - return mi_check_owned(p); + return mi_is_in_heap_region(p); } From 55a84827a776624afa793852e47f98bff38a6e1a Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 15:05:38 -0400 Subject: [PATCH 21/58] WIP: Testing if the unknown pointer comes from C++ new/delete allocator. --- resolve-cveassert/libresolve/src/remediate.rs | 29 +++++++++++++++++++ .../src/InstrumentAllocators.cpp | 2 ++ 2 files changed, 31 insertions(+) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 19708fa31..aec84154a 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -29,6 +29,8 @@ unsafe extern "C" { fn mi_strdup(ptr: *mut c_char) -> *mut c_char; fn mi_strndup(ptr: *mut c_char, size: usize) -> *mut c_char; fn mi_free(ptr: *mut c_void); + fn mi_new(size: usize) -> *mut c_void; + fn mi_delete(ptr: *mut c_void); // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; @@ -162,6 +164,18 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr } + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_new(size: usize) -> *mut c_void { + let ptr = unsafe { mi_new(size + 1) }; + + if ptr.is_null() { + return ptr; + } + + ptr +} + /** * @brief - RESOLVE wrapper for libc free * @input @@ -233,6 +247,21 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { let _ = unsafe { mi_free(ptr) }; } // + + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_delete(ptr: *mut c_void) -> () { + if ptr.is_null() { return; } + + unsafe { + let owned = mi_is_heap_owned(p); + if owned { + let_ = mi_free(ptr); + } else { + let _ = delete(ptr); + } + } +} /** * @brief - RESOLVE wrapper for libc realloc * @input diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index 8154d04ec..2e6fbeaaa 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -91,6 +91,8 @@ void instrumentLibraryAllocations(Function *F) { wrapLibraryFunction( F, "getdelim", FunctionType::get(size_ty, {ptr_ty, ptr_ty, size_ty, ptr_ty}, false)); + wrapLibraryFunction(F, "new", FunctionType::get(ptr_ty, {size_ty}, false)); + wrapLibraryFunction(F, "delete", FunctionType::get(void_ty, {ptr_ty}, false)); } void instrumentAlloca(Function *F) { From 530bfc13be24cfd29af19189fcb4be420db83936 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 12 Jun 2026 15:08:54 -0400 Subject: [PATCH 22/58] WIP: Fixing compilation issues. Testing if allocation comes from C++ new/delete. --- resolve-cveassert/libresolve/src/remediate.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index aec84154a..43e7e7d8b 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -252,15 +252,7 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { #[unsafe(no_mangle)] pub extern "C" fn __resolve_delete(ptr: *mut c_void) -> () { if ptr.is_null() { return; } - - unsafe { - let owned = mi_is_heap_owned(p); - if owned { - let_ = mi_free(ptr); - } else { - let _ = delete(ptr); - } - } + let _ = unsafe { mi_free(ptr) }; } /** * @brief - RESOLVE wrapper for libc realloc From 432fbd8c5b18e3680186fedd69aec77f53aaad20 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 09:51:20 -0400 Subject: [PATCH 23/58] remediate.rs: Debugging __resolve_free. --- resolve-cveassert/libresolve/src/remediate.rs | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 43e7e7d8b..078137273 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -1,5 +1,6 @@ // Copyright (c) 2025 Riverside Research. // LGPL-3; See LICENSE.txt in the repo root for details. + use libc::{ c_char, c_int, c_void, calloc, free, malloc, mmap, munmap, off_t, realloc, strdup, strlen, strndup, strnlen, @@ -130,14 +131,52 @@ pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t } } +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_t, delim: c_int, stream: *mut FILE) -> ssize_t { + if lineptr.is_null() || size.is_null() || stream.is_null() { + return -1; + } + + unsafe { + if (*lineptr).is_null() || *size == 0 { + *size = 128; + *lineptr = __resolve_malloc(*size) as *mut c_char; + + if (*lineptr).is_null() { return -1; } + } + + let mut pos: size_t = 0; + let mut c: c_int; + + loop { + c = fgetc(stream); + if c == EOF { break; } + + if pos + 1 >= *size { + let new_size = *size * 2; + let new_buf = __resolve_realloc(*lineptr as *mut c_void, new_size); + + if new_buf.is_null() { return -1; } + + *lineptr = new_buf as *mut c_char; + *size = new_size; + } + + (*lineptr).add(pos).write(c as c_char); + pos += 1; + if c == delim { break; } + } + + (*lineptr).add(pos).write(0); + pos as ssize_t + } +} /** - * @brief - RESOLVE wrapper for libc malloc - * @input - * - size: size of requested heap allocation in bytes - * @return - * - pointer to requested heap allocation + * @brief - Allocator logging interface for malloc + * @input - size of the allocation in bytes + * @return - ptr to the allocation */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { From 6e463739b2dbd0060b6d571271be0d88960cfe7e Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 10:55:42 -0400 Subject: [PATCH 24/58] WIP: Modified Cargo.toml to have cargo build with nightly and added __resolve_apsrintf to shim for testing. --- .../libresolve/mimalloc_shadow.c | 41 +++++++++++++++++++ .../src/InstrumentAllocators.cpp | 7 ++++ 2 files changed, 48 insertions(+) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 29ab840a4..240501f03 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -3,6 +3,9 @@ #include #include +extern void * __resolve_malloc(size_t); +extern void *__resolve_free(void*); + typedef struct { void *base; void *limit; @@ -35,3 +38,41 @@ bool mi_is_heap_owned(const void* p) { } +int __resolve_vasprintf(char **strp, const char *fmt, va_list ap) +{ + va_list ap_copy; + va_copy(ap_copy, ap); + + int len = vsnprintf(NULL, 0, fmt, ap_copy); + va_end(ap_copy); + + if (len < 0) { return -1; } + + char *buf = __resolve_malloc((size_t)len + 1); + if (!buf) { return -1; } + + va_copy(ap_copy, ap); + + int written = vsnprintf(buf, (size_t)len + 1, fmt, ap_copy); + + va_end(ap_copy); + + if (written < 0) { + __resolve_free(buf); + return -1; + } + + *strp = buf; + return written; +} + +int __resolve_asprintf(char **strp, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + int rc = __resolve_vasprintf(strp, fmt, ap); + + va_end(ap); + return rc; +} diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index 2e6fbeaaa..5d86844ab 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -93,6 +93,13 @@ void instrumentLibraryAllocations(Function *F) { FunctionType::get(size_ty, {ptr_ty, ptr_ty, size_ty, ptr_ty}, false)); wrapLibraryFunction(F, "new", FunctionType::get(ptr_ty, {size_ty}, false)); wrapLibraryFunction(F, "delete", FunctionType::get(void_ty, {ptr_ty}, false)); + wrapLibraryFunction(F, "asprintf", + FunctionType::get(size_ty, + { + ptr_ty, + ptr_ty, + }, + true)); } void instrumentAlloca(Function *F) { From c91caefde0c8a8eb938fdeee03bc08c31616f8c0 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 11:25:03 -0400 Subject: [PATCH 25/58] remediate.rs: WIP testing if __resolve_asprintf symbol shows up in libresolve. --- resolve-cveassert/libresolve/src/remediate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 078137273..9911ec18f 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -36,6 +36,7 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; + fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } /** From b2c2ebbb8a0ee99c9ba8a0fe4b039694d197157c Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 11:51:38 -0400 Subject: [PATCH 26/58] remediate.rs: WIP trying to get libresolve to resolve the __resolve_asprintf symbol. --- resolve-cveassert/libresolve/src/remediate.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 9911ec18f..7fe3fc53e 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -36,7 +36,6 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; - fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } /** @@ -174,6 +173,9 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } } +#[unsafe(no_mangle)] +unsafe extern "C" { fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } + /** * @brief - Allocator logging interface for malloc * @input - size of the allocation in bytes From eb1b1ed7c9719cd9da149238ec3f060e26252f92 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 12:03:02 -0400 Subject: [PATCH 27/58] WIP: try adding no_mangle to mimalloc symbols to have libresolve export symbols. --- resolve-cveassert/libresolve/src/remediate.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 7fe3fc53e..cf64e5642 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -22,6 +22,7 @@ struct BoundsInfo { } #[link(name = "mimalloc")] +#[unsafe(no_mangle)] unsafe extern "C" { // Allocator API fn mi_malloc(size: usize) -> *mut c_void; @@ -36,6 +37,7 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; + fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } /** @@ -173,9 +175,6 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } } -#[unsafe(no_mangle)] -unsafe extern "C" { fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } - /** * @brief - Allocator logging interface for malloc * @input - size of the allocation in bytes From 679d32dc9e23d23671decbbc1a2556b261709c34 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 13:08:32 -0400 Subject: [PATCH 28/58] WIP: Trying to debug why the __resolve_asprintf symbol is not being resolved correctly. --- resolve-cveassert/libresolve/src/remediate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index cf64e5642..857e19982 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -22,7 +22,6 @@ struct BoundsInfo { } #[link(name = "mimalloc")] -#[unsafe(no_mangle)] unsafe extern "C" { // Allocator API fn mi_malloc(size: usize) -> *mut c_void; @@ -37,6 +36,7 @@ unsafe extern "C" { // Shim API fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; + #[unsafe(no_mangle)] fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } From 4b217e7c2c41ae9a851bf4da355e0336e2696fa8 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 13:25:27 -0400 Subject: [PATCH 29/58] remediate.rs: WIP debugging __resolve_asprintf symbol export. --- resolve-cveassert/libresolve/src/remediate.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 857e19982..f9d721753 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -32,13 +32,17 @@ unsafe extern "C" { fn mi_free(ptr: *mut c_void); fn mi_new(size: usize) -> *mut c_void; fn mi_delete(ptr: *mut c_void); - - // Shim API - fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; - fn mi_is_heap_owned(ptr: *mut c_void) -> bool; - #[unsafe(no_mangle)] - fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; } + +#[unsafe(no_mangle)] +unsafe extern "C" { fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; } + +#[unsafe(no_mangle)] +unsafe extern "C" { fn mi_is_heap_owned(ptr: *mut c_void) -> bool; } + +#[unsafe(no_mangle)] +unsafe extern "C" { fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int ; } + /** * @brief - Registers stack allocations in shadow memory From 0ac13d7e718dd2c78d924b2829f35e608a86f382 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 14:40:17 -0400 Subject: [PATCH 30/58] WIP: debugging __resolve_asprintf symbol visibility and resolution. --- .../libresolve/mimalloc_shadow.c | 20 +++++++++++-------- resolve-cveassert/libresolve/src/remediate.rs | 19 +++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 240501f03..9c5e7379e 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -1,10 +1,12 @@ #include "mimalloc.h" #include "mimalloc/internal.h" +#include #include #include -extern void * __resolve_malloc(size_t); -extern void *__resolve_free(void*); +extern void* __resolve_malloc(size_t); +extern void __resolve_free(void*); + typedef struct { void *base; @@ -37,8 +39,7 @@ bool mi_is_heap_owned(const void* p) { return mi_is_in_heap_region(p); } - -int __resolve_vasprintf(char **strp, const char *fmt, va_list ap) +int __vasprintf(char **strp, const char *fmt, va_list ap) { va_list ap_copy; va_copy(ap_copy, ap); @@ -48,7 +49,8 @@ int __resolve_vasprintf(char **strp, const char *fmt, va_list ap) if (len < 0) { return -1; } - char *buf = __resolve_malloc((size_t)len + 1); + //char *buf = __resolve_malloc((size_t)len + 1); + char *buf = malloc((size_t)len + 1); if (!buf) { return -1; } va_copy(ap_copy, ap); @@ -58,7 +60,8 @@ int __resolve_vasprintf(char **strp, const char *fmt, va_list ap) va_end(ap_copy); if (written < 0) { - __resolve_free(buf); + //__resolve_free(buf); + free(buf); return -1; } @@ -66,12 +69,13 @@ int __resolve_vasprintf(char **strp, const char *fmt, va_list ap) return written; } -int __resolve_asprintf(char **strp, const char *fmt, ...) + +int __asprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int rc = __resolve_vasprintf(strp, fmt, ap); + int rc = __vasprintf(strp, fmt, ap); va_end(ap); return rc; diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index f9d721753..e3829448d 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -32,17 +32,11 @@ unsafe extern "C" { fn mi_free(ptr: *mut c_void); fn mi_new(size: usize) -> *mut c_void; fn mi_delete(ptr: *mut c_void); -} - -#[unsafe(no_mangle)] -unsafe extern "C" { fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; } - -#[unsafe(no_mangle)] -unsafe extern "C" { fn mi_is_heap_owned(ptr: *mut c_void) -> bool; } - -#[unsafe(no_mangle)] -unsafe extern "C" { fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int ; } + fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; + fn mi_is_heap_owned(ptr: *mut c_void) -> bool; + fn __asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; +} /** * @brief - Registers stack allocations in shadow memory @@ -179,6 +173,11 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } } +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int { + return __asprintf(strp, fmt, args) +} + /** * @brief - Allocator logging interface for malloc * @input - size of the allocation in bytes From 597823a0c9878f02bee73a013571ada92697472f Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 14:45:20 -0400 Subject: [PATCH 31/58] Fixing compilation issues. Ready to test __resolve_asprintf symbol resolution. --- resolve-cveassert/libresolve/src/remediate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index e3829448d..12a74f325 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -174,7 +174,7 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } #[unsafe(no_mangle)] -pub extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int { +pub unsafe extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int { return __asprintf(strp, fmt, args) } From 1cf352d22a55fbf4ef4b8a5bcd956081843612e8 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 15:21:11 -0400 Subject: [PATCH 32/58] WIP: Debugging ABI mismatch issues. --- .../libresolve/mimalloc_shadow.c | 24 ++++++------------- resolve-cveassert/libresolve/src/remediate.rs | 6 ++--- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 9c5e7379e..2cb50e162 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -47,10 +47,13 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) int len = vsnprintf(NULL, 0, fmt, ap_copy); va_end(ap_copy); - if (len < 0) { return -1; } + if (len < 0) { + // to match glibc behavior + *strp = NULL; + return -1; + } - //char *buf = __resolve_malloc((size_t)len + 1); - char *buf = malloc((size_t)len + 1); + char *buf = __resolve_malloc((size_t)len + 1); if (!buf) { return -1; } va_copy(ap_copy, ap); @@ -60,23 +63,10 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) va_end(ap_copy); if (written < 0) { - //__resolve_free(buf); - free(buf); + __resolve_free(buf); return -1; } *strp = buf; return written; } - - -int __asprintf(char **strp, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - int rc = __vasprintf(strp, fmt, ap); - - va_end(ap); - return rc; -} diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 12a74f325..9e23f5a9b 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -35,7 +35,7 @@ unsafe extern "C" { fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; - fn __asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int; + fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; } /** @@ -174,8 +174,8 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } #[unsafe(no_mangle)] -pub unsafe extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int { - return __asprintf(strp, fmt, args) +pub unsafe extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, mut args: ...) -> c_int { + return __vasprintf(strp, fmt, args) } /** From a53d664cca77c17264bd7e3a80efeb0d04ebedda Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 15 Jun 2026 15:40:05 -0400 Subject: [PATCH 33/58] mimalloc_shadow.c: Removed the plus one from len argument in __resolve_malloc. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 2cb50e162..99a602135 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -53,7 +53,7 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) return -1; } - char *buf = __resolve_malloc((size_t)len + 1); + char *buf = __resolve_malloc((size_t)len); if (!buf) { return -1; } va_copy(ap_copy, ap); From 5d61f0fd42c94600049362ea1aabf9417715fff0 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 16 Jun 2026 09:26:55 -0400 Subject: [PATCH 34/58] remediate.rs: Adding resolve wrappers for posx_memalign, reallocarray, aligned_alloc. --- resolve-cveassert/libresolve/src/lib.rs | 125 +++++++++++++++++ resolve-cveassert/libresolve/src/remediate.rs | 132 ++++++++++++------ .../src/InstrumentAllocators.cpp | 8 ++ 3 files changed, 224 insertions(+), 41 deletions(-) diff --git a/resolve-cveassert/libresolve/src/lib.rs b/resolve-cveassert/libresolve/src/lib.rs index 96428a485..ef3db2321 100644 --- a/resolve-cveassert/libresolve/src/lib.rs +++ b/resolve-cveassert/libresolve/src/lib.rs @@ -25,3 +25,128 @@ impl MutexWrap { self.mutex.lock() } } + +fn idify_file_path(path: &mut PathBuf, id: impl Display) { + let file_name = path + .file_name() + .expect("Path could not be found in file system.") + .to_owned(); + + let mut updated_file_name = OsString::new(); + + updated_file_name.push(file_name); + updated_file_name.push("-"); + updated_file_name.push(id.to_string()); + + path.set_file_name(updated_file_name); +} + +/// File for "resolve_dlsym.json" +pub static DLSYM_LOG_FILE: LazyLock> = LazyLock::new(|| { + let log_dir = env::var("RESOLVE_DLSYM_LOG_DIR").unwrap_or_else(|_| ".".to_string()); + + let mut path = PathBuf::from(log_dir); + + // Ensure the directory exists + fs::create_dir_all(&path).expect("Cannot create parent directories."); + + path.push("resolve_dlsym.json"); + + idify_file_path(&mut path, process::id()); + + let mut file = File::create(&path).expect("Cannot create file in directory."); + + // Write JSON header only once, when the file is first opened + let _ = write!(&mut file, "{{\n \"loaded_symbols\": [\n"); + + // SAFETY: flush_dlsym_log is extern "C" and takes no arguments. + // TODO: is DLSYM_LOG_FILE still valid during the atexit callback? + unsafe { atexit(flush_dlsym_log) }; + + MutexWrap::new(file) +}); + +#[used] +#[unsafe(link_section = ".init_array")] +static INIT_CTOR: extern "C" fn() = resolve_init; + +#[unsafe(no_mangle)] +pub extern "C" fn resolve_init() { + let mut builder = env_logger::builder(); + + if cfg!(test) { + builder.is_test(true); + } else { + let file = open_resolve_log_file().unwrap_or_else(|err| { + eprintln!("Libresolve log file could not be created."); + eprintln!("Error: {err:?}"); + process::exit(12); + }); + + builder.target(env_logger::Target::Pipe(Box::new(file))); + } + + let _ = builder.try_init(); +} + +fn open_resolve_log_file() -> Result { + let log_dir = env::var("RESOLVE_RUNTIME_LOG_DIR").unwrap_or_else(|_| ".".to_string()); + + let mut path = PathBuf::from(log_dir); + + // Ensure the parent directories exist + fs::create_dir_all(&path)?; + + // Append the file name + path.push("resolve_log.out"); + + idify_file_path(&mut path, process::id()); + File::create(&path) +} + +/** + * @brief - Writes JSON footer to the file descriptor + */ +#[unsafe(no_mangle)] +pub extern "C" fn flush_dlsym_log() { + let mut file = DLSYM_LOG_FILE.lock(); + + // Seek back 2 bytse to erase last ",\n" + file.seek_relative(-2).unwrap(); + + let _ = write!(&mut file, "\n ]\n}}\n"); +} + +/** + * @brief - Records and resolves dynamically linked symbols using dlsym + * @input - Pointer to dynamic loaded obj, name of symbol + * @return - C void type + */ +#[unsafe(no_mangle)] +pub extern "C" fn resolve_dlsym(handle: *mut c_void, symbol: *const u8) -> *mut c_void { + let addr = unsafe { dlsym(handle, symbol.cast()) }; + + let lib_name = unsafe { + let mut info: Dl_info = std::mem::zeroed(); + if dladdr(addr, &mut info) != 0 && !info.dli_fname.is_null() { + CStr::from_ptr(info.dli_fname) + } else { + c"" + } + }; + + let symbol = if !symbol.is_null() { + unsafe { CStr::from_ptr(symbol.cast::()) } + } else { + c"" + }; + + let _ = writeln!( + &mut DLSYM_LOG_FILE.lock(), + " {{ \"symbol\": \"{}\", \"library\": \"{}\" }},", + symbol.to_str().unwrap_or(""), + lib_name.to_str().unwrap_or("") + ); + + addr +} diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 9e23f5a9b..07279450a 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -23,12 +23,17 @@ struct BoundsInfo { #[link(name = "mimalloc")] unsafe extern "C" { - // Allocator API + // Allocator API fn mi_malloc(size: usize) -> *mut c_void; fn mi_calloc(size: usize, count: usize) -> *mut c_void; fn mi_realloc(ptr: *mut c_void, size: usize) -> *mut c_void; fn mi_strdup(ptr: *mut c_char) -> *mut c_char; fn mi_strndup(ptr: *mut c_char, size: usize) -> *mut c_char; + + fn mi_aligned_alloc(alignment: usize, n: usize) -> *mut c_void; + fn mi_reallocarray(ptr: *mut c_void, n: usize, size: usize) -> *mut c_void; + fn mi_posix_memalign(memptr: *mut *mut c_void, alignment: usize, size: usize) -> c_int; + fn mi_free(ptr: *mut c_void); fn mi_new(size: usize) -> *mut c_void; fn mi_delete(ptr: *mut c_void); @@ -79,7 +84,11 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize } #[unsafe(no_mangle)] -pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t, stream: *mut FILE) -> ssize_t { +pub extern "C" fn __resolve_getline( + lineptr: *mut *mut c_char, + size: *mut size_t, + stream: *mut FILE, +) -> ssize_t { if lineptr.is_null() || size.is_null() || stream.is_null() { return -1; } @@ -90,7 +99,9 @@ pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t *lineptr = __resolve_malloc(*size) as *mut c_char; // check if the pointer is null - if (*lineptr).is_null() { return -1; } + if (*lineptr).is_null() { + return -1; + } } let mut pos: size_t = 0; @@ -98,9 +109,12 @@ pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t loop { c = fgetc(stream); - if c == EOF { break; } + if c == EOF { + break; + } - if pos + 1 >= *size { // Expand buffer + if pos + 1 >= *size { + // Expand buffer let new_size = *size * 2; let new_buf = __resolve_realloc(*lineptr as *mut c_void, new_size); @@ -118,11 +132,11 @@ pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t if c == b'\n' as c_int { break; - } - + } } - if pos == 0 && c == EOF { // No data read + if pos == 0 && c == EOF { + // No data read return -1; } @@ -132,7 +146,12 @@ pub extern "C" fn __resolve_getline(lineptr: *mut *mut c_char, size: *mut size_t } #[unsafe(no_mangle)] -pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_t, delim: c_int, stream: *mut FILE) -> ssize_t { +pub extern "C" fn __resolve_getdelim( + lineptr: *mut *mut c_char, + size: *mut size_t, + delim: c_int, + stream: *mut FILE, +) -> ssize_t { if lineptr.is_null() || size.is_null() || stream.is_null() { return -1; } @@ -142,7 +161,9 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ *size = 128; *lineptr = __resolve_malloc(*size) as *mut c_char; - if (*lineptr).is_null() { return -1; } + if (*lineptr).is_null() { + return -1; + } } let mut pos: size_t = 0; @@ -150,14 +171,18 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ loop { c = fgetc(stream); - if c == EOF { break; } + if c == EOF { + break; + } if pos + 1 >= *size { let new_size = *size * 2; let new_buf = __resolve_realloc(*lineptr as *mut c_void, new_size); - if new_buf.is_null() { return -1; } - + if new_buf.is_null() { + return -1; + } + *lineptr = new_buf as *mut c_char; *size = new_size; } @@ -165,7 +190,9 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ (*lineptr).add(pos).write(c as c_char); pos += 1; - if c == delim { break; } + if c == delim { + break; + } } (*lineptr).add(pos).write(0); @@ -174,8 +201,31 @@ pub extern "C" fn __resolve_getdelim(lineptr: *mut *mut c_char, size: *mut size_ } #[unsafe(no_mangle)] -pub unsafe extern "C" fn __resolve_asprintf(strp: *mut *mut c_char, fmt: *const c_char, mut args: ...) -> c_int { - return __vasprintf(strp, fmt, args) +pub unsafe extern "C" fn __resolve_asprintf( + strp: *mut *mut c_char, + fmt: *const c_char, + args: ... +) -> c_int { + return unsafe { __vasprintf(strp, fmt, args) }; +} + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_aligned_alloc(alignment: usize, n: usize) -> *mut c_void { + return unsafe { mi_aligned_alloc(alignment, n) }; +} + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_posix_memalign( + memptr: *mut *mut c_void, + alignment: usize, + size: usize, +) -> c_int { + return unsafe { mi_posix_memalign(memptr, alignment, size) }; +} + +#[unsafe(no_mangle)] +pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize) -> *mut c_void { + return unsafe { mi_reallocarray(ptr, n, size + 1) }; } /** @@ -208,7 +258,6 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { ptr } - #[unsafe(no_mangle)] pub extern "C" fn __resolve_new(size: usize) -> *mut c_void { let ptr = unsafe { mi_new(size + 1) }; @@ -266,21 +315,21 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { // size // }; - // // Check if the shadow object exists - // match ptr_size { - // Some(size) => { - // info!( - // "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", - // ptr as Vaddr, - // ); - // } - // None => { - // warn!( - // "[FREE] No shadow object found for allocated object: 0x{:x}", - // ptr as Vaddr - // ); - // } - // } + // // Check if the shadow object exists + // match ptr_size { + // Some(size) => { + // info!( + // "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", + // ptr as Vaddr, + // ); + // } + // None => { + // warn!( + // "[FREE] No shadow object found for allocated object: 0x{:x}", + // ptr as Vaddr + // ); + // } + // } { // Insert shadow object into freed object list @@ -292,10 +341,11 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { } // - #[unsafe(no_mangle)] pub extern "C" fn __resolve_delete(ptr: *mut c_void) -> () { - if ptr.is_null() { return; } + if ptr.is_null() { + return; + } let _ = unsafe { mi_free(ptr) }; } /** @@ -333,7 +383,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi realloc_ptr, size ); - realloc_ptr + realloc_ptr } /** @@ -347,7 +397,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi #[unsafe(no_mangle)] pub extern "C" fn __resolve_calloc(n_items: usize, item_size: usize) -> *mut c_void { let ptr = unsafe { mi_calloc(n_items, item_size) }; - let size = n_items * item_size; + //let size = n_items * item_size; if ptr.is_null() { return ptr; @@ -384,11 +434,11 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { // +1 to include null termination byte. We should allow program to read this value. // Otherwise how would the program find the end of the string? // Although writing it to something else is probably a bad idea, this too should be allowed. - // let sizeofstr = unsafe { strlen(ptr) + 1 }; - // { - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); - // } + // let sizeofstr = unsafe { strlen(ptr) + 1 }; + // { + // let mut obj_list = ALIVE_OBJ_LIST.lock(); + // obj_list.add_shadow_object(AllocType::Heap, string_ptr as Vaddr, sizeofstr); + // } info!( "[HEAP] Registered heap object (strdup): addr={:p}, size={}", diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index 5d86844ab..52895c209 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -100,6 +100,14 @@ void instrumentLibraryAllocations(Function *F) { ptr_ty, }, true)); + wrapLibraryFunction(F, "aligned_alloc", + FunctionType::get(ptr_ty, {size_ty, size_ty}, false)); + wrapLibraryFunction( + F, "reallocarray", + FunctionType::get(ptr_ty, {ptr_ty, size_ty, size_ty}, false)); + wrapLibraryFunction( + F, "posix_memalign", + FunctionType::get(size_ty, {ptr_ty, size_ty, size_ty}, false)); } void instrumentAlloca(Function *F) { From 8265795abd4fa10e7e759fb2616c06f904d88b89 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 16 Jun 2026 14:43:35 -0400 Subject: [PATCH 35/58] remediate.rs: Testing without +1 padding. --- resolve-cveassert/libresolve/src/remediate.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 07279450a..a3b0edd30 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -225,7 +225,7 @@ pub extern "C" fn __resolve_posix_memalign( #[unsafe(no_mangle)] pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize) -> *mut c_void { - return unsafe { mi_reallocarray(ptr, n, size + 1) }; + return unsafe { mi_reallocarray(ptr, n, size) }; } /** @@ -235,7 +235,7 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { - let ptr = unsafe { mi_malloc(size + 1) }; + let ptr = unsafe { mi_malloc(size) }; //let bounds_info = unsafe { mi_resolve_ptr(ptr) }; if ptr.is_null() { @@ -260,7 +260,7 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { #[unsafe(no_mangle)] pub extern "C" fn __resolve_new(size: usize) -> *mut c_void { - let ptr = unsafe { mi_new(size + 1) }; + let ptr = unsafe { mi_new(size) }; if ptr.is_null() { return ptr; @@ -365,7 +365,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi // Consideration: Pointer passed in may be invalidated so we need a mechanism // to remove the shadow object for the orignal allocation - let realloc_ptr = unsafe { mi_realloc(ptr, size + 1) }; + let realloc_ptr = unsafe { mi_realloc(ptr, size) }; if realloc_ptr.is_null() { return realloc_ptr; @@ -459,7 +459,7 @@ pub extern "C" fn __resolve_strdup(ptr: *mut c_char) -> *mut c_char { */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_char { - let string_ptr = unsafe { mi_strndup(ptr, size + 1) }; + let string_ptr = unsafe { mi_strndup(ptr, size) }; if string_ptr.is_null() { return string_ptr; From fb1840e223bede1583fa33620ae1d7e484007002 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 16 Jun 2026 15:11:16 -0400 Subject: [PATCH 36/58] mimalloc_shadow.c: Testing __resolve_malloc call in __vasprintf --- resolve-cveassert/libresolve/mimalloc_shadow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 99a602135..2cb50e162 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -53,7 +53,7 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) return -1; } - char *buf = __resolve_malloc((size_t)len); + char *buf = __resolve_malloc((size_t)len + 1); if (!buf) { return -1; } va_copy(ap_copy, ap); From aab57b2683e6f6ee867709c98cefdb12fd44c3e5 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 08:18:01 -0400 Subject: [PATCH 37/58] mimalloc_shadow.c: Modified mi_is_heap_owned fn to return a boolean if the pointer is owned by a mimalloc allocation. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 2cb50e162..bce8ace49 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -17,6 +17,7 @@ typedef struct { bounds_info_t mi_resolve_ptr(void* p) { + // Can return null if ptr is not owned by mimalloc mi_page_t *page = _mi_ptr_page(p); const size_t block_size = page->block_size; @@ -36,7 +37,7 @@ bounds_info_t mi_resolve_ptr(void* p) { } bool mi_is_heap_owned(const void* p) { - return mi_is_in_heap_region(p); + return _mi_ptr_page(p) != NULL; } int __vasprintf(char **strp, const char *fmt, va_list ap) @@ -53,7 +54,7 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) return -1; } - char *buf = __resolve_malloc((size_t)len + 1); + char *buf = __resolve_malloc((size_t)len); if (!buf) { return -1; } va_copy(ap_copy, ap); From 32f5bc860fcaadb14311b2dff47aedff0640d33d Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 08:28:39 -0400 Subject: [PATCH 38/58] mimalloc_shadow.c: Adding +1 back to __resolve_malloc call. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index bce8ace49..84f0ae22e 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -54,7 +54,7 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) return -1; } - char *buf = __resolve_malloc((size_t)len); + char *buf = __resolve_malloc((size_t)len + 1); if (!buf) { return -1; } va_copy(ap_copy, ap); From a4d411a50d41e909aaddc9055f0321ef13d282af Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 09:58:15 -0400 Subject: [PATCH 39/58] remediate.rs: WIP checking the ptr and return address that is passed to __resolve_free. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 9 +++++++++ resolve-cveassert/libresolve/src/remediate.rs | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 84f0ae22e..62cc4bd35 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -71,3 +71,12 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) *strp = buf; return written; } + +void *resolve_return_address(unsigned level) { + switch(level) { + case 0: return __builtin_return_address(0); + case 1: return __builtin_return_address(1); + case 2: return __builtin_return_address(2); + default: return NULL; + } +} \ No newline at end of file diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index a3b0edd30..23e787b97 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -6,6 +6,8 @@ use libc::{ strndup, strnlen, }; +use std::ffi::VaList; + use crate::shadowobjs::{ ALIVE_OBJ_LIST, AllocType, FREED_OBJ_LIST, GLOBALS, SHADOW_STACK, ShadowObject, Vaddr, lookup_global, @@ -41,6 +43,7 @@ unsafe extern "C" { fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; + fn resolve_return_address(level: c_uint) -> *mut c_void; } /** @@ -235,7 +238,7 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { - let ptr = unsafe { mi_malloc(size) }; + let ptr = unsafe { mi_malloc(size + 1) }; //let bounds_info = unsafe { mi_resolve_ptr(ptr) }; if ptr.is_null() { From 9ef80ea96fbc763edd2c1e1696e379ac34161da7 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 14:27:18 -0400 Subject: [PATCH 40/58] shadowobjs.rs: Fixing compilation issue. --- resolve-cveassert/libresolve/src/shadowobjs.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/resolve-cveassert/libresolve/src/shadowobjs.rs b/resolve-cveassert/libresolve/src/shadowobjs.rs index 19e8ccf4e..1b62f6434 100644 --- a/resolve-cveassert/libresolve/src/shadowobjs.rs +++ b/resolve-cveassert/libresolve/src/shadowobjs.rs @@ -394,23 +394,12 @@ mod tests { // //table.print_shadow_obj(); // } -<<<<<<< HEAD - #[test] - fn test_remove_shadow_objects() { - let mut table = ShadowObjectTable::new(); - table.add_shadow_object(AllocType::Heap, 0x1000, 8); - table.add_shadow_object(AllocType::Stack, 0x2000, 16); - table.invalidate_at(0x1000); - assert_eq!(table.table.len(), 1); - } -======= // #[test] // fn test_remove_shadow_objects() { // let mut table = ShadowObjectTable::new(); // table.add_shadow_object(AllocType::Heap, 0x1000, 8); // table.add_shadow_object(AllocType::Stack, 0x2000, 16); // } ->>>>>>> ec6b0f1 (remediate.rs: Make sure all logging is commented out for poller testing.) // #[test] // fn test_search_intersection_found() { From d724b3ea0f6115119f90e26bed775e08fb168b7b Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 15:10:03 -0400 Subject: [PATCH 41/58] CMakeLists.txt: Fixing CMakeList file to correctly pass archive path to Cargo. --- resolve-cveassert/libresolve/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resolve-cveassert/libresolve/CMakeLists.txt b/resolve-cveassert/libresolve/CMakeLists.txt index ba5df5f55..709bc9dc1 100644 --- a/resolve-cveassert/libresolve/CMakeLists.txt +++ b/resolve-cveassert/libresolve/CMakeLists.txt @@ -23,12 +23,10 @@ target_sources(mimalloc-static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc_shadow.c ) -set(MIMALLOC_LIB_DIR ${mimalloc_BINARY_DIR}) -message(STATUS "MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR}") - ## mimalloc proj must be PIC to ensure compatibility with libresolve set_target_properties(mimalloc-static PROPERTIES POSITION_INDEPENDENT_CODE ON + OUTPUT_NAME mimalloc ) # Map CMake build type to Cargo flags @@ -53,7 +51,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${RUST_OUT_DIR} - MIMALLOC_LIB_DIR=${MIMALLOC_LIB_DIR} # pass the static mimalloc path + MIMALLOC_LIB_DIR=$ cargo build ${CARGO_FLAGS} WORKING_DIRECTORY ${RUST_CRATE_DIR} COMMENT "Building libresolve.so" VERBATIM From f368462307c69cc7d8c8bed4dbd9cb481d558464 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 18 Jun 2026 15:46:03 -0400 Subject: [PATCH 42/58] remediate.rs: Try using the mi_is_in_heap_region function to check if the pointer is within a mimalloc-owned mem region. --- resolve-cveassert/libresolve/src/remediate.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 23e787b97..c6a1aa073 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -40,10 +40,12 @@ unsafe extern "C" { fn mi_new(size: usize) -> *mut c_void; fn mi_delete(ptr: *mut c_void); + fn mi_is_in_heap_region(ptr: *mut c_void) -> bool; fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; fn resolve_return_address(level: c_uint) -> *mut c_void; + } /** From 69e20c86b2b414e6382c9c50796795edfd58faca Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 10:15:55 -0400 Subject: [PATCH 43/58] remediate.rs: Removed mi_is_heap_owned condition and modified C shim to return null pointers for pointers that are not allocated by mimalloc. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 62cc4bd35..44d750d8e 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -18,7 +18,15 @@ typedef struct { bounds_info_t mi_resolve_ptr(void* p) { // Can return null if ptr is not owned by mimalloc + bounds_info_t bounds; mi_page_t *page = _mi_ptr_page(p); + if (page == NULL) { + bounds.base = (void*)0; + bounds.limit = (void*)0; + bounds.block_size = 0; + bounds.block_index = 0; + return bounds; + } const size_t block_size = page->block_size; @@ -28,7 +36,6 @@ bounds_info_t mi_resolve_ptr(void* p) { size_t block_index = (ptr - page_start) / block_size; uintptr_t base_addr = page_start + block_index * block_size; - bounds_info_t bounds; bounds.base = (void*)base_addr; bounds.limit = (void*)(base_addr + block_size); bounds.block_size = block_size; @@ -71,12 +78,3 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) *strp = buf; return written; } - -void *resolve_return_address(unsigned level) { - switch(level) { - case 0: return __builtin_return_address(0); - case 1: return __builtin_return_address(1); - case 2: return __builtin_return_address(2); - default: return NULL; - } -} \ No newline at end of file From ea8b5086c0ab528a5569e3995658d9d2700b1468 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 10:41:24 -0400 Subject: [PATCH 44/58] remediate.rs: Adding debugger function to check if the pointer passed in image-histogram is an interior pointer. --- .../libresolve/mimalloc_shadow.c | 19 +++++++++++++++++++ resolve-cveassert/libresolve/src/remediate.rs | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 44d750d8e..4ac3e611b 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -78,3 +78,22 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) *strp = buf; return written; } + +/* debugging function to help check if a pointer the + base address or an offset into the block +*/ +bool mi_is_block_start(void *p) { + // Find the page + mi_page_t *page = _mi_ptr_page(p); + + // Compute the block index + const size_t block_size = page->block_size; + uintptr_t page_start = (uintptr_t)page->page_start; + size_t block_index = ((uintptr_t)p - page_start) / block_size; + + // Compute the canonical block base. + uintptr_t base = page_start + block_index * block_size; + + // Compare to pointer + return base == (uintptr_t)p; +} \ No newline at end of file diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index c6a1aa073..edc4e3738 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -44,7 +44,7 @@ unsafe extern "C" { fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; fn mi_is_heap_owned(ptr: *mut c_void) -> bool; fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; - fn resolve_return_address(level: c_uint) -> *mut c_void; + fn mi_is_block_start(ptr: *mut c_void) -> bool; } From 688145f9392e0016d7967dcd07f6cc05bd4e8118 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 13:05:13 -0400 Subject: [PATCH 45/58] remediate.rs: Adding logging to the C shim to determine where the pointer originates from. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 4ac3e611b..6c36efe47 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -83,9 +83,14 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) base address or an offset into the block */ bool mi_is_block_start(void *p) { + if (p == NULL) { return false; } + if (!mi_is_in_heap_region(p)) { return false; } + // Find the page mi_page_t *page = _mi_ptr_page(p); + if (page == NULL) { return false; } + // Compute the block index const size_t block_size = page->block_size; uintptr_t page_start = (uintptr_t)page->page_start; @@ -94,6 +99,14 @@ bool mi_is_block_start(void *p) { // Compute the canonical block base. uintptr_t base = page_start + block_index * block_size; + fprintf(stderr, + "p=%p page_start=%p block_size=%zu block_index=%zu base=%p\n", + p, + (void*)page_start, + block_size, + block_index, + (void*)base); + // Compare to pointer return base == (uintptr_t)p; } \ No newline at end of file From ac9ed1725127c321f744900d6422fec8b799743e Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 13:30:07 -0400 Subject: [PATCH 46/58] remediate.rs: Reverting back to an earlier commit. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 6c36efe47..8155bf159 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -84,8 +84,6 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) */ bool mi_is_block_start(void *p) { if (p == NULL) { return false; } - if (!mi_is_in_heap_region(p)) { return false; } - // Find the page mi_page_t *page = _mi_ptr_page(p); From 09bd459acb3ffe9fbc019d8aaaae6fca6eb2d506 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 15:56:44 -0400 Subject: [PATCH 47/58] remediate.rs: Adding logging to help with debugging. --- resolve-cveassert/libresolve/src/remediate.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index edc4e3738..19a9f4a8c 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -242,6 +242,7 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { let ptr = unsafe { mi_malloc(size + 1) }; //let bounds_info = unsafe { mi_resolve_ptr(ptr) }; + info!("[RESOLVE] mimalloc ptr: 0x{:x}", ptr as Vaddr); if ptr.is_null() { return ptr; @@ -372,6 +373,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi // to remove the shadow object for the orignal allocation let realloc_ptr = unsafe { mi_realloc(ptr, size) }; + info!("[RESOLVE] old = 0x{:x}, new = 0x:{x}, size = {}", ptr as Vaddr, realloc_ptr as Vaddr, size); if realloc_ptr.is_null() { return realloc_ptr; } From 75e74440d7816de601a73cb4634d0f36e0ff1f91 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 16:00:41 -0400 Subject: [PATCH 48/58] remediate.rs: Fixing compilation issue. --- resolve-cveassert/libresolve/src/remediate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 19a9f4a8c..3ff624375 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -373,7 +373,7 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi // to remove the shadow object for the orignal allocation let realloc_ptr = unsafe { mi_realloc(ptr, size) }; - info!("[RESOLVE] old = 0x{:x}, new = 0x:{x}, size = {}", ptr as Vaddr, realloc_ptr as Vaddr, size); + info!("[RESOLVE] old = 0x{:x}, new = 0x{:x}, size = {}", ptr as Vaddr, realloc_ptr as Vaddr, size); if realloc_ptr.is_null() { return realloc_ptr; } From f6f942015ef767478c8d076376b8b5e9a928bf72 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 22 Jun 2026 16:34:58 -0400 Subject: [PATCH 49/58] remediate.rs: Removed logging from C shim and checking if the weird pointer is within the region of mimalloc. --- resolve-cveassert/libresolve/mimalloc_shadow.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index 8155bf159..e4f177659 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -96,15 +96,7 @@ bool mi_is_block_start(void *p) { // Compute the canonical block base. uintptr_t base = page_start + block_index * block_size; - - fprintf(stderr, - "p=%p page_start=%p block_size=%zu block_index=%zu base=%p\n", - p, - (void*)page_start, - block_size, - block_index, - (void*)base); - + // Compare to pointer return base == (uintptr_t)p; } \ No newline at end of file From 526d9bb5b107efd186f01aa0bdcbc04bef593268 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 29 Jun 2026 11:53:50 -0400 Subject: [PATCH 50/58] mimalloc_shadow.c: WIP updating C shim to use mi_usable_size to get the correct allocation size. --- .../libresolve/mimalloc_shadow.c | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mimalloc_shadow.c index e4f177659..9dbcd84dc 100644 --- a/resolve-cveassert/libresolve/mimalloc_shadow.c +++ b/resolve-cveassert/libresolve/mimalloc_shadow.c @@ -1,3 +1,6 @@ +// Copyright (c) 2025 Riverside Research. +// LGPL-3; See LICENSE.txt in the repo root for details. + #include "mimalloc.h" #include "mimalloc/internal.h" #include @@ -11,22 +14,28 @@ extern void __resolve_free(void*); typedef struct { void *base; void *limit; - size_t block_size; - size_t block_index; -} bounds_info_t; + size_t size; +} mi_alloc_bounds_t; -bounds_info_t mi_resolve_ptr(void* p) { - // Can return null if ptr is not owned by mimalloc - bounds_info_t bounds; - mi_page_t *page = _mi_ptr_page(p); - if (page == NULL) { +mi_alloc_bounds_t mi_get_alloc_bounds(void* p) { + mi_alloc_bounds_t bounds; + mi_alloc_bounds_t empty = { .base = (void*) -1, .limit = (void*)-1, .size = 0 }; + + // Check if ptr is owned by mimalloc + if (!mi_is_in_heap_region(p)) { bounds.base = (void*)0; bounds.limit = (void*)0; - bounds.block_size = 0; - bounds.block_index = 0; + bounds.size = 0; return bounds; } + + // Recover the page information for the pointer. + mi_page_t *page = _mi_ptr_page(p); + + if (page == NULL) { + return empty; + } const size_t block_size = page->block_size; @@ -34,12 +43,12 @@ bounds_info_t mi_resolve_ptr(void* p) { uintptr_t ptr = (uintptr_t)p; size_t block_index = (ptr - page_start) / block_size; - uintptr_t base_addr = page_start + block_index * block_size; + uintptr_t base = page_start + block_index * block_size; - bounds.base = (void*)base_addr; - bounds.limit = (void*)(base_addr + block_size); - bounds.block_size = block_size; - bounds.block_index = block_index; + void *base_ptr = (void *)base; + bounds.base = base_ptr; + bounds.size = mi_usable_size(base_ptr); + bounds.limit = base_ptr + bounds.size; return bounds; } @@ -84,7 +93,8 @@ int __vasprintf(char **strp, const char *fmt, va_list ap) */ bool mi_is_block_start(void *p) { if (p == NULL) { return false; } - // Find the page + + // Recover page information mi_page_t *page = _mi_ptr_page(p); if (page == NULL) { return false; } @@ -94,7 +104,7 @@ bool mi_is_block_start(void *p) { uintptr_t page_start = (uintptr_t)page->page_start; size_t block_index = ((uintptr_t)p - page_start) / block_size; - // Compute the canonical block base. + // Compute the canonical base. uintptr_t base = page_start + block_index * block_size; // Compare to pointer From 72906334996a06eb2fdd9a47ee833e832a7077d6 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Mon, 29 Jun 2026 11:55:25 -0400 Subject: [PATCH 51/58] Updating name of C shim source file to mi_shim.c --- resolve-cveassert/libresolve/CMakeLists.txt | 2 +- resolve-cveassert/libresolve/{mimalloc_shadow.c => mi_shim.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename resolve-cveassert/libresolve/{mimalloc_shadow.c => mi_shim.c} (100%) diff --git a/resolve-cveassert/libresolve/CMakeLists.txt b/resolve-cveassert/libresolve/CMakeLists.txt index 709bc9dc1..f123038d5 100644 --- a/resolve-cveassert/libresolve/CMakeLists.txt +++ b/resolve-cveassert/libresolve/CMakeLists.txt @@ -20,7 +20,7 @@ FetchContent_MakeAvailable(mimalloc) # Add the shim source to the mimalloc proj target_sources(mimalloc-static PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc_shadow.c + ${CMAKE_CURRENT_SOURCE_DIR}/mi_shim.c ) ## mimalloc proj must be PIC to ensure compatibility with libresolve diff --git a/resolve-cveassert/libresolve/mimalloc_shadow.c b/resolve-cveassert/libresolve/mi_shim.c similarity index 100% rename from resolve-cveassert/libresolve/mimalloc_shadow.c rename to resolve-cveassert/libresolve/mi_shim.c From 09c1bddb15c729c4810b733c8d14ba2f8df70a47 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 30 Jun 2026 13:42:21 -0400 Subject: [PATCH 52/58] remediate.rs: Fixing some issues with rebasing. Updating mimalloc_integration to include Ryan's changes. --- resolve-cveassert/libresolve/src/remediate.rs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 3ff624375..b8775e8d7 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -665,21 +665,21 @@ pub extern "C" fn __resolve_get_bounds(ptr: *mut c_void) -> ShadowObjBounds { sobj } -// -//#[unsafe(no_mangle)] -//pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { -// let base = base_ptr as Vaddr; -// -// let find_in = |table: &crate::MutexWrap| { -// let t = table.lock(); -// t.search_intersection(base).map(|o| o.alloc_type) -// }; -// -// // Why does this search freed before alive? -// let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); -// -// alloc_type.unwrap_or(AllocType::Unknown) -//} + +#[unsafe(no_mangle)] +pub extern "C" fn resolve_obj_type(base_ptr: *mut c_void) -> AllocType { + let base = base_ptr as Vaddr; + + let find_in = |table: &crate::MutexWrap| { + let t = table.lock(); + t.search_intersection(base).map(|o| o.alloc_type) + }; + + // Why does this search freed before alive? + let alloc_type = find_in(&FREED_OBJ_LIST).or_else(|| find_in(&ALIVE_OBJ_LIST)); + + alloc_type.unwrap_or(AllocType::Unknown) +} /** * @brief - Logs invalid memory access for a given function From fc91e82f39d32b8d5370d5f7ddb7ad1e8d3b41e7 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 30 Jun 2026 14:34:57 -0400 Subject: [PATCH 53/58] remediate.rs: Adding From trait for AllocBounds type, removed some commented code from runtime functions, and adding info!() to debug allocation bounds returned from mimalloc. --- resolve-cveassert/libresolve/src/remediate.rs | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index b8775e8d7..c0e36c40f 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -15,12 +15,18 @@ use crate::shadowobjs::{ use log::{info, warn}; +#[derive(PartialEq)] #[repr(C)] -struct BoundsInfo { +struct AllocBounds { base: *mut c_void, limit: *mut c_void, - block_size: usize, - block_index: usize, + size: usize, +} + +impl From for ShadowObjBounds { + fn from(bounds: AllocBounds) -> Self { + ShadowObjBounds { base: bounds.base, limit: bounds.limit } + } } #[link(name = "mimalloc")] @@ -41,10 +47,9 @@ unsafe extern "C" { fn mi_delete(ptr: *mut c_void); fn mi_is_in_heap_region(ptr: *mut c_void) -> bool; - fn mi_resolve_ptr(ptr: *mut c_void) -> BoundsInfo; - fn mi_is_heap_owned(ptr: *mut c_void) -> bool; - fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; + fn mi_get_alloc_bounds(ptr: *mut c_void) -> AllocBounds; fn mi_is_block_start(ptr: *mut c_void) -> bool; + fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; } @@ -619,33 +624,18 @@ pub extern "C" fn __resolve_get_bounds_stack(ptr: *mut c_void) -> ShadowObjBound */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_get_bounds_heap(ptr: *mut c_void) -> ShadowObjBounds { - let sobj_table = ALIVE_OBJ_LIST.lock(); - let Some(sobj) = sobj_table.search_intersection(ptr as Vaddr) else { + if ptr.is_null() { return ShadowObjBounds::null(); - }; + } - return sobj.into(); -} + let bounds = unsafe { mi_get_alloc_bounds(ptr) }; + info!("[RESOLVE] (ptr: 0x{:x}, lower: 0x{:x}, upper: 0x{:x})", ptr as Vaddr, bounds.base as Vaddr, bounds.limit as Vaddr); -/** - * @brief - Queries recorded globals to find a shadow obj - * where the ptr is within bounds of allocation - * @input - * - ptr: ptr to global allocation - * @return shadow object that satisfies base <= ptr && ptr < limit - * If shadow object cannot be found the function returns - * a shadow object with null base and limit pointers - */ -#[unsafe(no_mangle)] -pub extern "C" fn __resolve_get_bounds_global(ptr: *mut c_void) -> ShadowObjBounds { - match lookup_global(ptr as Vaddr) { - Some(obj) => (&obj).into(), - None => ShadowObjBounds::null(), - } + return sobj.into(); } /** - * @brief - Generic shadow object lookup where we don't know the pointers + * @brief - Generic sobj lookup where we don't know the pointers * allocation type already. Searches stack table ( O(log n) ) * before searching the heap table * @input @@ -663,7 +653,7 @@ pub extern "C" fn __resolve_get_bounds(ptr: *mut c_void) -> ShadowObjBounds { sobj = __resolve_get_bounds_global(ptr) } - sobj + bounds } #[unsafe(no_mangle)] From 0ecd2debea1ebd9781d24cfaded7080bffee3367 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Wed, 1 Jul 2026 08:24:08 -0400 Subject: [PATCH 54/58] remediate.rs: Removed comment from __resolve_malloc wrapper. --- resolve-cveassert/libresolve/src/remediate.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index c0e36c40f..25c01c27b 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -246,7 +246,6 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { let ptr = unsafe { mi_malloc(size + 1) }; - //let bounds_info = unsafe { mi_resolve_ptr(ptr) }; info!("[RESOLVE] mimalloc ptr: 0x{:x}", ptr as Vaddr); if ptr.is_null() { From b279a95f3057e29e8f8973c785efd242db581508 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Thu, 2 Jul 2026 08:06:02 -0400 Subject: [PATCH 55/58] remediate.rs: Adding some safety comments to unsafe blocks. --- resolve-cveassert/libresolve/src/remediate.rs | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 25c01c27b..051933355 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -25,13 +25,16 @@ struct AllocBounds { impl From for ShadowObjBounds { fn from(bounds: AllocBounds) -> Self { - ShadowObjBounds { base: bounds.base, limit: bounds.limit } + ShadowObjBounds { + base: bounds.base, + limit: bounds.limit, + } } } #[link(name = "mimalloc")] unsafe extern "C" { - // Allocator API + // Mimalloc public API fn mi_malloc(size: usize) -> *mut c_void; fn mi_calloc(size: usize, count: usize) -> *mut c_void; fn mi_realloc(ptr: *mut c_void, size: usize) -> *mut c_void; @@ -46,11 +49,12 @@ unsafe extern "C" { fn mi_new(size: usize) -> *mut c_void; fn mi_delete(ptr: *mut c_void); + // mi_shim.c API fn mi_is_in_heap_region(ptr: *mut c_void) -> bool; fn mi_get_alloc_bounds(ptr: *mut c_void) -> AllocBounds; fn mi_is_block_start(ptr: *mut c_void) -> bool; fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; - + } /** @@ -245,6 +249,8 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize */ #[unsafe(no_mangle)] pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { + // SAFETY: + // - 'ptr' allocated by mimalloc let ptr = unsafe { mi_malloc(size + 1) }; info!("[RESOLVE] mimalloc ptr: 0x{:x}", ptr as Vaddr); @@ -325,21 +331,21 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { // size // }; - // // Check if the shadow object exists - // match ptr_size { - // Some(size) => { - // info!( - // "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", - // ptr as Vaddr, - // ); - // } - // None => { - // warn!( - // "[FREE] No shadow object found for allocated object: 0x{:x}", - // ptr as Vaddr - // ); - // } - // } +// // Check if the shadow object exists +// match ptr_size { +// Some(size) => { +// info!( +// "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", +// ptr as Vaddr, +// ); +// } +// None => { +// warn!( +// "[FREE] No shadow object found for allocated object: 0x{:x}", +// ptr as Vaddr +// ); +// } +// } { // Insert shadow object into freed object list @@ -377,7 +383,10 @@ pub extern "C" fn __resolve_realloc(ptr: *mut c_void, size: usize) -> *mut c_voi // to remove the shadow object for the orignal allocation let realloc_ptr = unsafe { mi_realloc(ptr, size) }; - info!("[RESOLVE] old = 0x{:x}, new = 0x{:x}, size = {}", ptr as Vaddr, realloc_ptr as Vaddr, size); + info!( + "[RESOLVE] old = 0x{:x}, new = 0x{:x}, size = {}", + ptr as Vaddr, realloc_ptr as Vaddr, size + ); if realloc_ptr.is_null() { return realloc_ptr; } @@ -627,8 +636,13 @@ pub extern "C" fn __resolve_get_bounds_heap(ptr: *mut c_void) -> ShadowObjBounds return ShadowObjBounds::null(); } + // SAFETY: + // 'ptr' must point to valid allocation owned by mimalloc let bounds = unsafe { mi_get_alloc_bounds(ptr) }; - info!("[RESOLVE] (ptr: 0x{:x}, lower: 0x{:x}, upper: 0x{:x})", ptr as Vaddr, bounds.base as Vaddr, bounds.limit as Vaddr); + info!( + "[RESOLVE] (ptr: 0x{:x}, lower: 0x{:x}, upper: 0x{:x})", + ptr as Vaddr, bounds.base as Vaddr, bounds.limit as Vaddr + ); return sobj.into(); } From 3345c2482625a9be23c01078274565fd3b19789a Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Tue, 7 Jul 2026 13:13:52 -0400 Subject: [PATCH 56/58] WIP: Pushing updates for mimalloc integration. --- resolve-cveassert/libresolve/mi_shim.c | 28 ++++++++----------- resolve-cveassert/libresolve/src/remediate.rs | 8 +++--- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/resolve-cveassert/libresolve/mi_shim.c b/resolve-cveassert/libresolve/mi_shim.c index 9dbcd84dc..e4c90710a 100644 --- a/resolve-cveassert/libresolve/mi_shim.c +++ b/resolve-cveassert/libresolve/mi_shim.c @@ -24,10 +24,7 @@ mi_alloc_bounds_t mi_get_alloc_bounds(void* p) { // Check if ptr is owned by mimalloc if (!mi_is_in_heap_region(p)) { - bounds.base = (void*)0; - bounds.limit = (void*)0; - bounds.size = 0; - return bounds; + return empty; } // Recover the page information for the pointer. @@ -37,18 +34,14 @@ mi_alloc_bounds_t mi_get_alloc_bounds(void* p) { return empty; } - const size_t block_size = page->block_size; - - uintptr_t page_start = (uintptr_t)page->page_start; - uintptr_t ptr = (uintptr_t)p; - - size_t block_index = (ptr - page_start) / block_size; - uintptr_t base = page_start + block_index * block_size; - - void *base_ptr = (void *)base; - bounds.base = base_ptr; - bounds.size = mi_usable_size(base_ptr); - bounds.limit = base_ptr + bounds.size; + // _mi_page_ptr_unalign recovers the corresponding + // block for base and interior pointers + mi_block_t *base = _mi_page_ptr_unalign(page, p); + if (!base) { return empty; } + + bounds.base = (void *)base; + bounds.size = mi_usable_size(base); + bounds.limit = (void *)base + bounds.size; return bounds; } @@ -109,4 +102,5 @@ bool mi_is_block_start(void *p) { // Compare to pointer return base == (uintptr_t)p; -} \ No newline at end of file +} + diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index 051933355..c94800a79 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -17,7 +17,7 @@ use log::{info, warn}; #[derive(PartialEq)] #[repr(C)] -struct AllocBounds { +pub struct AllocBounds { base: *mut c_void, limit: *mut c_void, size: usize, @@ -31,6 +31,7 @@ impl From for ShadowObjBounds { } } } +// implement the From Trait for AllocBounds #[link(name = "mimalloc")] unsafe extern "C" { @@ -52,9 +53,8 @@ unsafe extern "C" { // mi_shim.c API fn mi_is_in_heap_region(ptr: *mut c_void) -> bool; fn mi_get_alloc_bounds(ptr: *mut c_void) -> AllocBounds; - fn mi_is_block_start(ptr: *mut c_void) -> bool; fn __vasprintf(strp: *mut *mut c_char, fmt: *const c_char, args: VaList<'_>) -> c_int; - + fn mi_is_block_start(ptr: *mut c_void) -> bool; } /** @@ -252,7 +252,7 @@ pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { // SAFETY: // - 'ptr' allocated by mimalloc let ptr = unsafe { mi_malloc(size + 1) }; - info!("[RESOLVE] mimalloc ptr: 0x{:x}", ptr as Vaddr); + info!("[RESOLVE] mi_malloc ptr: 0x{:x}", ptr as Vaddr); if ptr.is_null() { return ptr; From 91089e7139d0475e2d3c083b6cc7532c233c7040 Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 28 Aug 2026 10:49:31 -0400 Subject: [PATCH 57/58] InstrumentAllocators.cpp: Updating type variable names. --- .../src/InstrumentAllocators.cpp | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/resolve-cveassert/src/InstrumentAllocators.cpp b/resolve-cveassert/src/InstrumentAllocators.cpp index 52895c209..9914a7720 100644 --- a/resolve-cveassert/src/InstrumentAllocators.cpp +++ b/resolve-cveassert/src/InstrumentAllocators.cpp @@ -87,27 +87,29 @@ void instrumentLibraryAllocations(Function *F) { F, "munmap", FunctionType::get(integerType, {ptrType, sizeType}, false)); wrapLibraryFunction( F, "getline", - FunctionType::get(size_ty, {ptr_ty, ptr_ty, ptr_ty}, false)); - wrapLibraryFunction( - F, "getdelim", - FunctionType::get(size_ty, {ptr_ty, ptr_ty, size_ty, ptr_ty}, false)); - wrapLibraryFunction(F, "new", FunctionType::get(ptr_ty, {size_ty}, false)); - wrapLibraryFunction(F, "delete", FunctionType::get(void_ty, {ptr_ty}, false)); + FunctionType::get(sizeType, {ptrType, ptrType, ptrType}, false)); + wrapLibraryFunction(F, "getdelim", + FunctionType::get(sizeType, + {ptrType, ptrType, sizeType, ptrType}, + false)); + wrapLibraryFunction(F, "new", FunctionType::get(ptrType, {sizeType}, false)); + wrapLibraryFunction(F, "delete", + FunctionType::get(voidType, {ptrType}, false)); wrapLibraryFunction(F, "asprintf", - FunctionType::get(size_ty, + FunctionType::get(sizeType, { - ptr_ty, - ptr_ty, + ptrType, + ptrType, }, true)); wrapLibraryFunction(F, "aligned_alloc", - FunctionType::get(ptr_ty, {size_ty, size_ty}, false)); + FunctionType::get(ptrType, {sizeType, sizeType}, false)); wrapLibraryFunction( F, "reallocarray", - FunctionType::get(ptr_ty, {ptr_ty, size_ty, size_ty}, false)); + FunctionType::get(ptrType, {ptrType, sizeType, sizeType}, false)); wrapLibraryFunction( F, "posix_memalign", - FunctionType::get(size_ty, {ptr_ty, size_ty, size_ty}, false)); + FunctionType::get(sizeType, {ptrType, sizeType, sizeType}, false)); } void instrumentAlloca(Function *F) { From 6479ed5dd10cd7157d053c284a3b8994f89fda9e Mon Sep 17 00:00:00 2001 From: Ethan Lazaro Date: Fri, 28 Aug 2026 11:04:48 -0400 Subject: [PATCH 58/58] Formatting rust files. --- resolve-cveassert/libresolve/src/lib.rs | 125 ----------------- resolve-cveassert/libresolve/src/remediate.rs | 127 +++++++----------- .../libresolve/src/shadowobjs.rs | 78 +++++------ 3 files changed, 90 insertions(+), 240 deletions(-) diff --git a/resolve-cveassert/libresolve/src/lib.rs b/resolve-cveassert/libresolve/src/lib.rs index ef3db2321..96428a485 100644 --- a/resolve-cveassert/libresolve/src/lib.rs +++ b/resolve-cveassert/libresolve/src/lib.rs @@ -25,128 +25,3 @@ impl MutexWrap { self.mutex.lock() } } - -fn idify_file_path(path: &mut PathBuf, id: impl Display) { - let file_name = path - .file_name() - .expect("Path could not be found in file system.") - .to_owned(); - - let mut updated_file_name = OsString::new(); - - updated_file_name.push(file_name); - updated_file_name.push("-"); - updated_file_name.push(id.to_string()); - - path.set_file_name(updated_file_name); -} - -/// File for "resolve_dlsym.json" -pub static DLSYM_LOG_FILE: LazyLock> = LazyLock::new(|| { - let log_dir = env::var("RESOLVE_DLSYM_LOG_DIR").unwrap_or_else(|_| ".".to_string()); - - let mut path = PathBuf::from(log_dir); - - // Ensure the directory exists - fs::create_dir_all(&path).expect("Cannot create parent directories."); - - path.push("resolve_dlsym.json"); - - idify_file_path(&mut path, process::id()); - - let mut file = File::create(&path).expect("Cannot create file in directory."); - - // Write JSON header only once, when the file is first opened - let _ = write!(&mut file, "{{\n \"loaded_symbols\": [\n"); - - // SAFETY: flush_dlsym_log is extern "C" and takes no arguments. - // TODO: is DLSYM_LOG_FILE still valid during the atexit callback? - unsafe { atexit(flush_dlsym_log) }; - - MutexWrap::new(file) -}); - -#[used] -#[unsafe(link_section = ".init_array")] -static INIT_CTOR: extern "C" fn() = resolve_init; - -#[unsafe(no_mangle)] -pub extern "C" fn resolve_init() { - let mut builder = env_logger::builder(); - - if cfg!(test) { - builder.is_test(true); - } else { - let file = open_resolve_log_file().unwrap_or_else(|err| { - eprintln!("Libresolve log file could not be created."); - eprintln!("Error: {err:?}"); - process::exit(12); - }); - - builder.target(env_logger::Target::Pipe(Box::new(file))); - } - - let _ = builder.try_init(); -} - -fn open_resolve_log_file() -> Result { - let log_dir = env::var("RESOLVE_RUNTIME_LOG_DIR").unwrap_or_else(|_| ".".to_string()); - - let mut path = PathBuf::from(log_dir); - - // Ensure the parent directories exist - fs::create_dir_all(&path)?; - - // Append the file name - path.push("resolve_log.out"); - - idify_file_path(&mut path, process::id()); - File::create(&path) -} - -/** - * @brief - Writes JSON footer to the file descriptor - */ -#[unsafe(no_mangle)] -pub extern "C" fn flush_dlsym_log() { - let mut file = DLSYM_LOG_FILE.lock(); - - // Seek back 2 bytse to erase last ",\n" - file.seek_relative(-2).unwrap(); - - let _ = write!(&mut file, "\n ]\n}}\n"); -} - -/** - * @brief - Records and resolves dynamically linked symbols using dlsym - * @input - Pointer to dynamic loaded obj, name of symbol - * @return - C void type - */ -#[unsafe(no_mangle)] -pub extern "C" fn resolve_dlsym(handle: *mut c_void, symbol: *const u8) -> *mut c_void { - let addr = unsafe { dlsym(handle, symbol.cast()) }; - - let lib_name = unsafe { - let mut info: Dl_info = std::mem::zeroed(); - if dladdr(addr, &mut info) != 0 && !info.dli_fname.is_null() { - CStr::from_ptr(info.dli_fname) - } else { - c"" - } - }; - - let symbol = if !symbol.is_null() { - unsafe { CStr::from_ptr(symbol.cast::()) } - } else { - c"" - }; - - let _ = writeln!( - &mut DLSYM_LOG_FILE.lock(), - " {{ \"symbol\": \"{}\", \"library\": \"{}\" }},", - symbol.to_str().unwrap_or(""), - lib_name.to_str().unwrap_or("") - ); - - addr -} diff --git a/resolve-cveassert/libresolve/src/remediate.rs b/resolve-cveassert/libresolve/src/remediate.rs index c94800a79..a12401c38 100644 --- a/resolve-cveassert/libresolve/src/remediate.rs +++ b/resolve-cveassert/libresolve/src/remediate.rs @@ -6,7 +6,7 @@ use libc::{ strndup, strnlen, }; -use std::ffi::VaList; +use std::ffi::{CStr, VaList}; use crate::shadowobjs::{ ALIVE_OBJ_LIST, AllocType, FREED_OBJ_LIST, GLOBALS, SHADOW_STACK, ShadowObject, Vaddr, @@ -94,7 +94,7 @@ pub extern "C" fn __resolve_invalidate_stack_range(ptr: *mut c_void, size: usize SHADOW_STACK.with_borrow_mut(|ss| ss.invalidate_at(base, size)); - info!("[STACK] Free addr 0x{base:x} size {size}"); + info!("[STACK] Free addr={:p}, size={}", ptr, size); } #[unsafe(no_mangle)] @@ -155,8 +155,8 @@ pub extern "C" fn __resolve_getline( } (*lineptr).add(pos).write(0); // (*lineptr)[pos] = '\0' - pos as ssize_t } + pos as ssize_t } #[unsafe(no_mangle)] @@ -251,20 +251,19 @@ pub extern "C" fn __resolve_reallocarray(ptr: *mut c_void, n: usize, size: usize pub extern "C" fn __resolve_malloc(size: usize) -> *mut c_void { // SAFETY: // - 'ptr' allocated by mimalloc - let ptr = unsafe { mi_malloc(size + 1) }; - info!("[RESOLVE] mi_malloc ptr: 0x{:x}", ptr as Vaddr); + let ptr = unsafe { mi_malloc(size) }; if ptr.is_null() { return ptr; } - //{ - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); - //} + { + let mut obj_list = ALIVE_OBJ_LIST.lock(); + obj_list.add_shadow_object(AllocType::Heap, ptr as Vaddr, size); + } info!( - "[HEAP] Registered heap object (malloc): addr={:p}, size={}", + "[HEAP] Registered heap object (mi_malloc): addr={:p}, size={}", ptr, size ); @@ -309,7 +308,6 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { ptr as Vaddr, ); -<<<<<<< HEAD info!( "[HEAP] Unregistered heap object: addr={:p}, size={}", ptr, size @@ -321,31 +319,7 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { ptr as Vaddr ); } -======= - // let ptr_size = { - // let mut obj_list = ALIVE_OBJ_LIST.lock(); - // let sobj_opt = obj_list.search_intersection(ptr as Vaddr); - // let size = sobj_opt.map(|o| o.size()); - // // remove shadow obj from live list - // obj_list.invalidate_at(ptr as Vaddr); - // size - // }; - -// // Check if the shadow object exists -// match ptr_size { -// Some(size) => { -// info!( -// "[FREE] Found shadow object for allocated object, 0x{:x}, size = {size}", -// ptr as Vaddr, -// ); -// } -// None => { -// warn!( -// "[FREE] No shadow object found for allocated object: 0x{:x}", -// ptr as Vaddr -// ); -// } -// } + } { // Insert shadow object into freed object list @@ -353,9 +327,8 @@ pub extern "C" fn __resolve_free(ptr: *mut c_void) -> () { freed_guard.add_shadow_object(AllocType::Unallocated, ptr as Vaddr, obj_size.unwrap_or(0)); } - let _ = unsafe { mi_free(ptr) }; + let _ = unsafe { mi_free(ptr) }; } -// #[unsafe(no_mangle)] pub extern "C" fn __resolve_delete(ptr: *mut c_void) -> () { @@ -501,8 +474,8 @@ pub extern "C" fn __resolve_strndup(ptr: *mut c_char, size: usize) -> *mut c_cha string_ptr, sizeofstr ); -// string_ptr -// } + string_ptr +} /** * @brief - RESOLVE wrapper for libc mmap @@ -713,41 +686,41 @@ mod tests { use crate::file::resolve_init; use crate::shadowobjs::AllocType; - #[test] - fn test_malloc_free() { - resolve_init(); - // Allocation should successfully return a memory block - let ptr = __resolve_malloc(0x10); - assert!(!ptr.is_null()); - - // We should track the obj correctly - { - let table = ALIVE_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_some()); - let obj = obj.unwrap(); - assert!(obj.size() == 0x10); - assert!(obj.base == ptr as Vaddr); - assert!(obj.alloc_type == AllocType::Heap); - } - - __resolve_free(ptr); - - // After freeing a block we should track that it has been freed - { - let table = FREED_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_some()); - } - - // And it should no longer be in the alive obj list. - { - let table = ALIVE_OBJ_LIST.lock(); - let obj = table.search_intersection(ptr as Vaddr); - - assert!(obj.is_none()); - } - } + #[test] + fn test_malloc_free() { + resolve_init(); + // Allocation should successfully return a memory block + let ptr = __resolve_malloc(0x10); + assert!(!ptr.is_null()); + + // We should track the obj correctly + { + let table = ALIVE_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_some()); + let obj = obj.unwrap(); + assert!(obj.size() == 0x10); + assert!(obj.base == ptr as Vaddr); + assert!(obj.alloc_type == AllocType::Heap); + } + + __resolve_free(ptr); + + // After freeing a block we should track that it has been freed + { + let table = FREED_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_some()); + } + + // And it should no longer be in the alive obj list. + { + let table = ALIVE_OBJ_LIST.lock(); + let obj = table.search_intersection(ptr as Vaddr); + + assert!(obj.is_none()); + } + } } diff --git a/resolve-cveassert/libresolve/src/shadowobjs.rs b/resolve-cveassert/libresolve/src/shadowobjs.rs index 1b62f6434..05f5b8c19 100644 --- a/resolve-cveassert/libresolve/src/shadowobjs.rs +++ b/resolve-cveassert/libresolve/src/shadowobjs.rs @@ -391,30 +391,32 @@ mod tests { table.add_shadow_object(AllocType::Heap, 0x1000, 8); table.add_shadow_object(AllocType::Stack, 0x2000, 16); -// //table.print_shadow_obj(); -// } - -// #[test] -// fn test_remove_shadow_objects() { -// let mut table = ShadowObjectTable::new(); -// table.add_shadow_object(AllocType::Heap, 0x1000, 8); -// table.add_shadow_object(AllocType::Stack, 0x2000, 16); -// } - -// #[test] -// fn test_search_intersection_found() { -// let mut table = ShadowObjectTable::new(); -// table.add_shadow_object(AllocType::Global, 0x3000, 4); - -// let result = table.search_intersection(0x3002); -// assert!(result.is_some()); -// assert_eq!(result.unwrap().alloc_type, AllocType::Global); -// } - -// #[test] -// fn test_search_intersection_not_found() { -// let mut table = ShadowObjectTable::new(); -// table.add_shadow_object(AllocType::Heap, 0x4000, 4); + //table.print_shadow_obj(); + } + + #[test] + fn test_remove_shadow_objects() { + let mut table = ShadowObjectTable::new(); + table.add_shadow_object(AllocType::Heap, 0x1000, 8); + table.add_shadow_object(AllocType::Stack, 0x2000, 16); + table.invalidate_at(0x1000); + assert_eq!(table.table.len(), 1); + } + + #[test] + fn test_search_intersection_found() { + let mut table = ShadowObjectTable::new(); + table.add_shadow_object(AllocType::Global, 0x3000, 4); + + let result = table.search_intersection(0x3002); + assert!(result.is_some()); + assert_eq!(result.unwrap().alloc_type, AllocType::Global); + } + + #[test] + fn test_search_intersection_not_found() { + let mut table = ShadowObjectTable::new(); + table.add_shadow_object(AllocType::Heap, 0x4000, 4); let result = table.search_intersection(0x5000); assert!(result.is_none()); @@ -440,22 +442,22 @@ mod tests { GLOBALS.lock().clear(); } -// #[test] -// fn test_is_allocation() { -// let mut table = ShadowObjectTable::new(); -// table.add_shadow_object(AllocType::Stack, 0x6000, 8); + #[test] + fn test_is_allocation() { + let mut table = ShadowObjectTable::new(); + table.add_shadow_object(AllocType::Stack, 0x6000, 8); -// let typ = table.search_intersection(0x6004).unwrap().alloc_type; -// assert_eq!(typ, AllocType::Stack); -// } -// #[test] -// fn bounds_testing() { -// let mut table = ShadowObjectTable::new(); -// table.add_shadow_object(AllocType::Heap, 0x8000, 8); + let typ = table.search_intersection(0x6004).unwrap().alloc_type; + assert_eq!(typ, AllocType::Stack); + } + #[test] + fn bounds_testing() { + let mut table = ShadowObjectTable::new(); + table.add_shadow_object(AllocType::Heap, 0x8000, 8); -// for x in 0x8000..0x8008 { -// assert!(table.search_intersection(x).is_some()); -// } + for x in 0x8000..0x8008 { + assert!(table.search_intersection(x).is_some()); + } assert!(table.search_intersection(0x8009).is_none()); assert!(table.search_intersection(0x7FFF).is_none());