-
Notifications
You must be signed in to change notification settings - Fork 50
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 fatal runtime panic passing invalid pointer #40
Conversation
The last argument to hs_scan is "void*", a pointer to an abitrary context. "hsScan" incorrectly uses "unsafe.Pointer(h)" when h is not a pointer. This can cause fatal runtime panic when Go passes arguments across the Go <-> C boundaries. This does not happen all the time, as it usually "looks" like a pointer. In reality, h is an unsigned long value belonging to "handles". We can coerce this into "void*" on the C side with the added "safe_hs_scan"
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.
All of the other functions in the package that carry a void* context will want a similar treatment.
See golang/go#49633, which suggests a much simpler solution of passing the address of the cgo.Handle through the C code. |
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.
LGTM
@@ -1013,7 +1009,8 @@ type hsMatchEventContext struct { | |||
|
|||
//export hsMatchEventCallback | |||
func hsMatchEventCallback(id C.uint, from, to C.ulonglong, flags C.uint, data unsafe.Pointer) C.int { | |||
ctx, ok := handle.Handle(data).Value().(hsMatchEventContext) | |||
h := (*handle.Handle)(data) |
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.
*(*handle.Handle)(data)
The current code is not wrong because of the implicit dereference in h.Value, but h should be a Handle, not a pointer to one.
Well, this is indeed an unthought of problem, thank you very much for your hard work :) |
The last argument to hs_scan is "void*", a pointer to an abitrary
context. "hsScan" incorrectly uses "unsafe.Pointer(h)" when h is not a
pointer. This can cause fatal runtime error when Go passes arguments
across the Go <-> C boundaries. The runtime error does not happen all
the time, as it usually "looks" like a pointer. This makes it difficult
to reproduce.
We can fix this by actually passing a real pointer (of our
cgo.Handle
)and dereferencing the pointer within the callback. I did a quick audit,
and think I updated all places where we use the callback.
I did not audit other parts of the API spec that take in a
void*
arg.Thanks @adonovan for helping with most of the analysis.
Below is a small snippet of the fatal runtime panic: