-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix validate exception handling #473
Fix validate exception handling #473
Conversation
} | ||
|
||
JS_FreeValue(ctx, val); | ||
// We don't manually free the bytecode object (obj) here because | ||
// JS_EvalFunction internally transforms it into a closure and takes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on all the context we've gathered, here's a comprehensive explanation of the bytecode function memory management issue in QuickJS:
The Core Issue
When you create a bytecode function via JS_ReadObject(..., JS_READ_OBJ_BYTECODE)
and then execute it with JS_EvalFunction()
, a specific memory management pattern occurs that makes manual cleanup problematic.
What Happens During Evaluation
When JS_EvalFunction()
is called on a bytecode function object:
- The function is identified as having the tag
JS_TAG_FUNCTION_BYTECODE
- A new function object (closure) is created via
js_closure()
- Inside
js_closure2()
, the original bytecode's internalJSFunctionBytecode
structure is directly assigned to the new closure:p->u.func.function_bytecode = b
- The new closure is executed and then freed by
JS_CallFree()
- When the closure is freed, it frees the shared
JSFunctionBytecode
structure
The Problematic Scenarios
This sharing of the internal structure creates two problematic scenarios:
-
Attempting to evaluate a bytecode function twice:
- First evaluation works fine
- During first evaluation, the internal structure is freed when the closure is freed
- Second evaluation attempts to use the freed structure, causing a crash
-
Manually freeing a bytecode function after evaluation:
- Evaluation creates a closure that takes ownership of the internal structure
- The closure is freed after execution, which frees the internal structure
- Manual call to
JS_FreeValue()
on the original bytecode function attempts to free the already freed structure, causing a crash
The Solution
The safe approach is to let QuickJS's garbage collection handle the cleanup:
- Create bytecode function
- Evaluate it (which internally transforms and executes it)
- Don't manually free it
- Let the context cleanup handle it when
JS_FreeContext()
is called
Best Practice
For safe handling of bytecode functions:
- Evaluate each bytecode function exactly once
- Never manually free a bytecode function after evaluation
- Let context destruction handle the cleanup
This pattern avoids the double-free issues while still allowing efficient execution of bytecode functions.
Manually squash merged |
This PR improves exception handling in the QuickJS bindings by addressing two key issues:
handleException
helper that extracts Error#message property and frees variadic JSValue argsAdditionally:
JS_Eval()
(usingstrlen()
instead ofsizeof()
)