Skip to content

fix: defer removed hook callback drops - #16

Open
Jvlegod wants to merge 1 commit into
unicorn-engine:mainfrom
Jvlegod:fix/defer-hook-callback-drop
Open

fix: defer removed hook callback drops#16
Jvlegod wants to merge 1 commit into
unicorn-engine:mainfrom
Jvlegod:fix/defer-hook-callback-drop

Conversation

@Jvlegod

@Jvlegod Jvlegod commented Aug 13, 2026

Copy link
Copy Markdown

Hello maintainers,

I noticed issues with the current hook mechanism and have therefore made the following modifications.

This mechanism introduces a nesting counter parameter and briefly retains removed hooks until it is confirmed that the simulation has concluded.

Note: a similar method already exists in the unicorn core.

see:

@Jvlegod
Jvlegod force-pushed the fix/defer-hook-callback-drop branch from e95b34d to 8414ded Compare August 13, 2026 08:33
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
@Jvlegod
Jvlegod force-pushed the fix/defer-hook-callback-drop branch from 8414ded to 33a6bea Compare August 13, 2026 08:35
@PhilippTakacs

Copy link
Copy Markdown
Contributor

I'm not get what problem you want to solve. As you noticed unicorn does this already, so why do it again in the rust bindings?

@Jvlegod

Jvlegod commented Aug 13, 2026

Copy link
Copy Markdown
Author

As you noticed unicorn does this already, so why do it again in the rust bindings?

unicorns do exist in this way.

However, in the rust bindings:

Previously, when remove_hook was called, the Rust callback was immediately freed; however, unicorn might still use it during nested execution, potentially leading to access of already freed memory.

Therefore, the goal here is to ensure that both the rust callback and the unicorn hook are released at the same time.

more easily example:

let hook_id = Rc::new(Cell::new(None));

let hook = uc.add_code_hook(CODE_START, CODE_START, move |uc, _, _| {
    // remove callback's hook
    // The callback might be dropped early while it is executing,
    // even though the lifetime of the hook has not yet ended.
    uc.remove_hook(hook_id.get().unwrap()).unwrap();
    uc.emu_start(CODE_START + 1, CODE_START + 2, 0, 0).unwrap();
}).unwrap();

hook_id.set(Some(hook));

You can see here :> :

inner.hooks.retain(|(id, _)| id != &hook_id);

Original code: when a matching hook_id is found and removed, the callback in rust is immediately dropped.

What is your take on this issue? :>

Note: Also due to the delayed deallocation mechanism(In C API), unicorn's C core library still holds an internal user_data pointer referencing this memory, which has already been freed by rust(Maybe I think).

@PhilippTakacs

Copy link
Copy Markdown
Contributor

unicorn might still use it during nested execution

This is a bug, when a hook is deleted it should not be called again.

Can you test if unicorn-engine/unicorn#2253 fixes your issue?

@Jvlegod

Jvlegod commented Aug 13, 2026

Copy link
Copy Markdown
Author

Can you test if unicorn-engine/unicorn#2253 fixes your issue?

sure, I will reply here as soon as I have finished testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants