Skip to content

Commit 121c165

Browse files
committed
Pass length to free register list callback
Allows language bindings like rust to free register lists sanely
1 parent 487fa4b commit 121c165

File tree

8 files changed

+126
-93
lines changed

8 files changed

+126
-93
lines changed

architecture.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ size_t Architecture::GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t
530530
}
531531

532532

533-
void Architecture::FreeRegisterListCallback(void*, uint32_t* regs)
533+
void Architecture::FreeRegisterListCallback(void*, uint32_t* regs, size_t)
534534
{
535535
delete[] regs;
536536
}

binaryninjaapi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7940,7 +7940,7 @@ namespace BinaryNinja {
79407940
static size_t GetFlagConditionLowLevelILCallback(
79417941
void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il);
79427942
static size_t GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il);
7943-
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs);
7943+
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs, size_t len);
79447944
static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result);
79457945
static uint32_t GetStackPointerRegisterCallback(void* ctxt);
79467946
static uint32_t GetLinkRegisterCallback(void* ctxt);
@@ -15026,7 +15026,7 @@ namespace BinaryNinja {
1502615026
static uint32_t* GetCalleeSavedRegistersCallback(void* ctxt, size_t* count);
1502715027
static uint32_t* GetIntegerArgumentRegistersCallback(void* ctxt, size_t* count);
1502815028
static uint32_t* GetFloatArgumentRegistersCallback(void* ctxt, size_t* count);
15029-
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs);
15029+
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs, size_t len);
1503015030

1503115031
static bool AreArgumentRegistersSharedIndexCallback(void* ctxt);
1503215032
static bool AreArgumentRegistersUsedForVarArgsCallback(void* ctxt);

binaryninjacore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,7 @@ extern "C"
18621862
size_t (*getFlagConditionLowLevelIL)(
18631863
void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il);
18641864
size_t (*getSemanticFlagGroupLowLevelIL)(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il);
1865-
void (*freeRegisterList)(void* ctxt, uint32_t* regs);
1865+
void (*freeRegisterList)(void* ctxt, uint32_t* regs, size_t count);
18661866
void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result);
18671867
uint32_t (*getStackPointerRegister)(void* ctxt);
18681868
uint32_t (*getLinkRegister)(void* ctxt);
@@ -2541,7 +2541,7 @@ extern "C"
25412541
uint32_t* (*getCalleeSavedRegisters)(void* ctxt, size_t* count);
25422542
uint32_t* (*getIntegerArgumentRegisters)(void* ctxt, size_t* count);
25432543
uint32_t* (*getFloatArgumentRegisters)(void* ctxt, size_t* count);
2544-
void (*freeRegisterList)(void* ctxt, uint32_t* regs);
2544+
void (*freeRegisterList)(void* ctxt, uint32_t* regs, size_t len);
25452545

25462546
bool (*areArgumentRegistersSharedIndex)(void* ctxt);
25472547
bool (*isStackReservedForArgumentRegisters)(void* ctxt);

callingconvention.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ uint32_t* CallingConvention::GetFloatArgumentRegistersCallback(void* ctxt, size_
119119
}
120120

121121

122-
void CallingConvention::FreeRegisterListCallback(void*, uint32_t* regs)
122+
void CallingConvention::FreeRegisterListCallback(void*, uint32_t* regs, size_t)
123123
{
124124
delete[] regs;
125125
}

python/architecture.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ def _get_semantic_flag_group_low_level_il(self, ctxt, sem_group, il):
999999
log_error(traceback.format_exc())
10001000
return 0
10011001

1002-
def _free_register_list(self, ctxt, regs):
1002+
def _free_register_list(self, ctxt, regs, count):
10031003
try:
10041004
buf = ctypes.cast(regs, ctypes.c_void_p)
10051005
if buf.value not in self._pending_reg_lists:

python/callingconvention.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def _get_float_arg_regs(self, ctxt, count):
281281
count[0] = 0
282282
return None
283283

284-
def _free_register_list(self, ctxt, regs):
284+
def _free_register_list(self, ctxt, regs, count):
285285
try:
286286
buf = ctypes.cast(regs, ctypes.c_void_p)
287287
if buf.value not in self._pending_reg_lists:

rust/src/architecture.rs

Lines changed: 84 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,104 +1941,117 @@ where
19411941
None => BnString::new("invalid_flag_group").into_raw(),
19421942
}
19431943
}
1944-
1945-
fn alloc_register_list<I: Iterator<Item = u32> + ExactSizeIterator>(
1946-
items: I,
1947-
count: &mut usize,
1948-
) -> *mut u32 {
1949-
let len = items.len();
1950-
*count = len;
1951-
1952-
if len == 0 {
1953-
ptr::null_mut()
1954-
} else {
1955-
let mut res: Box<[_]> = [len as u32].into_iter().chain(items).collect();
1956-
1957-
let raw = res.as_mut_ptr();
1958-
mem::forget(res);
1959-
1960-
unsafe { raw.offset(1) }
1961-
}
1962-
}
1963-
1944+
19641945
extern "C" fn cb_registers_full_width<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
19651946
where
19661947
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
19671948
{
19681949
let custom_arch = unsafe { &*(ctxt as *mut A) };
1969-
let regs = custom_arch.registers_full_width();
1950+
let mut regs = custom_arch.registers_full_width();
19701951

1971-
alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
1952+
// SAFETY: `count` is an out parameter
1953+
unsafe { *count = regs.len() };
1954+
let regs_ptr = regs.as_mut_ptr();
1955+
mem::forget(regs);
1956+
regs_ptr as *mut _
19721957
}
19731958

19741959
extern "C" fn cb_registers_all<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
19751960
where
19761961
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
19771962
{
19781963
let custom_arch = unsafe { &*(ctxt as *mut A) };
1979-
let regs = custom_arch.registers_all();
1964+
let mut regs = custom_arch.registers_all();
19801965

1981-
alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
1966+
// SAFETY: `count` is an out parameter
1967+
unsafe { *count = regs.len() };
1968+
let regs_ptr = regs.as_mut_ptr();
1969+
mem::forget(regs);
1970+
regs_ptr as *mut _
19821971
}
19831972

19841973
extern "C" fn cb_registers_global<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
19851974
where
19861975
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
19871976
{
19881977
let custom_arch = unsafe { &*(ctxt as *mut A) };
1989-
let regs = custom_arch.registers_global();
1978+
let mut regs = custom_arch.registers_global();
19901979

1991-
alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
1980+
// SAFETY: `count` is an out parameter
1981+
unsafe { *count = regs.len() };
1982+
let regs_ptr = regs.as_mut_ptr();
1983+
mem::forget(regs);
1984+
regs_ptr as *mut _
19921985
}
19931986

19941987
extern "C" fn cb_registers_system<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
19951988
where
19961989
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
19971990
{
19981991
let custom_arch = unsafe { &*(ctxt as *mut A) };
1999-
let regs = custom_arch.registers_system();
1992+
let mut regs = custom_arch.registers_system();
20001993

2001-
alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
1994+
// SAFETY: `count` is an out parameter
1995+
unsafe { *count = regs.len() };
1996+
let regs_ptr = regs.as_mut_ptr();
1997+
mem::forget(regs);
1998+
regs_ptr as *mut _
20021999
}
20032000

20042001
extern "C" fn cb_flags<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
20052002
where
20062003
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
20072004
{
20082005
let custom_arch = unsafe { &*(ctxt as *mut A) };
2009-
let flags = custom_arch.flags();
2006+
let mut flags = custom_arch.flags();
20102007

2011-
alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
2008+
// SAFETY: `count` is an out parameter
2009+
unsafe { *count = flags.len() };
2010+
let regs_ptr = flags.as_mut_ptr();
2011+
mem::forget(flags);
2012+
regs_ptr as *mut _
20122013
}
20132014

20142015
extern "C" fn cb_flag_write_types<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
20152016
where
20162017
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
20172018
{
20182019
let custom_arch = unsafe { &*(ctxt as *mut A) };
2019-
let flag_writes = custom_arch.flag_write_types();
2020+
let mut flag_writes = custom_arch.flag_write_types();
20202021

2021-
alloc_register_list(flag_writes.iter().map(|r| r.id()), unsafe { &mut *count })
2022+
// SAFETY: `count` is an out parameter
2023+
unsafe { *count = flag_writes.len() };
2024+
let regs_ptr = flag_writes.as_mut_ptr();
2025+
mem::forget(flag_writes);
2026+
regs_ptr as *mut _
20222027
}
20232028

20242029
extern "C" fn cb_semantic_flag_classes<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
20252030
where
20262031
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
20272032
{
20282033
let custom_arch = unsafe { &*(ctxt as *mut A) };
2029-
let flag_classes = custom_arch.flag_classes();
2034+
let mut flag_classes = custom_arch.flag_classes();
20302035

2031-
alloc_register_list(flag_classes.iter().map(|r| r.id()), unsafe { &mut *count })
2036+
// SAFETY: `count` is an out parameter
2037+
unsafe { *count = flag_classes.len() };
2038+
let regs_ptr = flag_classes.as_mut_ptr();
2039+
mem::forget(flag_classes);
2040+
regs_ptr as *mut _
20322041
}
20332042

20342043
extern "C" fn cb_semantic_flag_groups<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
20352044
where
20362045
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
20372046
{
20382047
let custom_arch = unsafe { &*(ctxt as *mut A) };
2039-
let flag_groups = custom_arch.flag_groups();
2048+
let mut flag_groups = custom_arch.flag_groups();
20402049

2041-
alloc_register_list(flag_groups.iter().map(|r| r.id()), unsafe { &mut *count })
2050+
// SAFETY: `count` is an out parameter
2051+
unsafe { *count = flag_groups.len() };
2052+
let regs_ptr = flag_groups.as_mut_ptr();
2053+
mem::forget(flag_groups);
2054+
regs_ptr as *mut _
20422055
}
20432056

20442057
extern "C" fn cb_flag_role<A>(ctxt: *mut c_void, flag: u32, class: u32) -> BNFlagRole
@@ -2068,9 +2081,13 @@ where
20682081
{
20692082
let custom_arch = unsafe { &*(ctxt as *mut A) };
20702083
let class = custom_arch.flag_class_from_id(class);
2071-
let flags = custom_arch.flags_required_for_flag_condition(cond, class);
2084+
let mut flags = custom_arch.flags_required_for_flag_condition(cond, class);
20722085

2073-
alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
2086+
// SAFETY: `count` is an out parameter
2087+
unsafe { *count = flags.len() };
2088+
let regs_ptr = flags.as_mut_ptr();
2089+
mem::forget(flags);
2090+
regs_ptr as *mut _
20742091
}
20752092

20762093
extern "C" fn cb_flags_required_for_semantic_flag_group<A>(
@@ -2084,8 +2101,13 @@ where
20842101
let custom_arch = unsafe { &*(ctxt as *mut A) };
20852102

20862103
if let Some(group) = custom_arch.flag_group_from_id(group) {
2087-
let flags = group.flags_required();
2088-
alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
2104+
let mut flags = group.flags_required();
2105+
2106+
// SAFETY: `count` is an out parameter
2107+
unsafe { *count = flags.len() };
2108+
let regs_ptr = flags.as_mut_ptr();
2109+
mem::forget(flags);
2110+
regs_ptr as *mut _
20892111
} else {
20902112
unsafe {
20912113
*count = 0;
@@ -2153,8 +2175,13 @@ where
21532175
let custom_arch = unsafe { &*(ctxt as *mut A) };
21542176

21552177
if let Some(write_type) = custom_arch.flag_write_from_id(write_type) {
2156-
let written = write_type.flags_written();
2157-
alloc_register_list(written.iter().map(|f| f.id()), unsafe { &mut *count })
2178+
let mut written = write_type.flags_written();
2179+
2180+
// SAFETY: `count` is an out parameter
2181+
unsafe { *count = written.len() };
2182+
let regs_ptr = written.as_mut_ptr();
2183+
mem::forget(written);
2184+
regs_ptr as *mut _
21582185
} else {
21592186
unsafe {
21602187
*count = 0;
@@ -2285,15 +2312,13 @@ where
22852312
lifter.unimplemented().expr_idx
22862313
}
22872314

2288-
extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32) {
2315+
extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32, count: usize) {
22892316
if regs.is_null() {
22902317
return;
22912318
}
22922319

22932320
unsafe {
2294-
let actual_start = regs.offset(-1);
2295-
let len = *actual_start + 1;
2296-
let regs_ptr = ptr::slice_from_raw_parts_mut(actual_start, len.try_into().unwrap());
2321+
let regs_ptr = ptr::slice_from_raw_parts_mut(regs, count);
22972322
let _regs = Box::from_raw(regs_ptr);
22982323
}
22992324
}
@@ -2362,9 +2387,13 @@ where
23622387
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
23632388
{
23642389
let custom_arch = unsafe { &*(ctxt as *mut A) };
2365-
let regs = custom_arch.register_stacks();
2390+
let mut regs = custom_arch.register_stacks();
23662391

2367-
alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
2392+
// SAFETY: Passed in to be written
2393+
unsafe { *count = regs.len() };
2394+
let regs_ptr = regs.as_mut_ptr();
2395+
mem::forget(regs);
2396+
regs_ptr as *mut _
23682397
}
23692398

23702399
extern "C" fn cb_reg_stack_info<A>(
@@ -2420,8 +2449,13 @@ where
24202449
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
24212450
{
24222451
let custom_arch = unsafe { &*(ctxt as *mut A) };
2423-
let intrinsics = custom_arch.intrinsics();
2424-
alloc_register_list(intrinsics.iter().map(|i| i.id()), unsafe { &mut *count })
2452+
let mut intrinsics = custom_arch.intrinsics();
2453+
2454+
// SAFETY: Passed in to be written
2455+
unsafe { *count = intrinsics.len() };
2456+
let regs_ptr = intrinsics.as_mut_ptr();
2457+
mem::forget(intrinsics);
2458+
regs_ptr as *mut _
24252459
}
24262460

24272461
extern "C" fn cb_intrinsic_inputs<A>(

0 commit comments

Comments
 (0)