Skip to content
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

feat(InstanceContext): Avoid passing illegal pointers across CGo FFI … #83

Closed

Conversation

AdamSLevy
Copy link
Contributor

@AdamSLevy AdamSLevy commented Nov 16, 2019

…for user data

Previously an unsafe.Pointer to user data was passed across the CGo FFI
which resulted in a panic if the user data included any other Go
pointers. This commit adds a global ctxData registry and assigns a
unique int id to each Instance that calls SetContextData. This id is
stored in the actual C Instance Context Data that crosses the CGo FFI
and is used to look up the actual user data. A sync.RWMutex is used to
synchronize access to the ctxData map.

BREAKING CHANGE: This changes the API for Instance.SetContextData and
InstanceContext.Data to accept and return an interface{} instead of an
unsafe.Pointer.

re #44

Additional details

This approach is an improvement on the approach being used in the Gossamer project's runtime package.

I believe the work around for this limitation should be built directly into this package, because while it is fairly simple, there are subtleties that are easy to miss.

At minimum, the documentation of Instance.SetContextData() should be updated to mention this limitation. Issue #44 is an example of confusion about this limitation.

@AdamSLevy AdamSLevy force-pushed the InstanceContextDataRegistry branch 3 times, most recently from 4e24271 to f9066be Compare November 16, 2019 21:49
@AdamSLevy
Copy link
Contributor Author

The latest force-push has all tests passing now.

…for user data

Previously an unsafe.Pointer to user data was passed across the CGo FFI
which resulted in a panic if the user data included any other Go
pointers. This commit adds a global ctxData registry and assigns a
unique int id to each Instance that calls SetContextData. This id is
stored in the actual C Instance Context Data that crosses the CGo FFI
and is used to look up the actual user data. A sync.RWMutex is used to
synchronize access to the ctxData map.

BREAKING CHANGE: This changes the API for Instance.SetContextData and
InstanceContext.Data to accept and return an interface{} instead of an
unsafe.Pointer.

re wasmerio#44
@AdamSLevy AdamSLevy force-pushed the InstanceContextDataRegistry branch from f9066be to 61347df Compare November 16, 2019 22:00
@Hywan Hywan self-assigned this Nov 18, 2019
@Hywan Hywan added 🎉 enhancement New feature or request 📦 component-runtime About the Wasm runtime labels Nov 18, 2019
@Hywan
Copy link
Contributor

Hywan commented Nov 18, 2019

cc @losfair

@losfair
Copy link

losfair commented Nov 18, 2019

Would it be better to store a pointer to data interface{} in an Instance field (to prevent it from being GC-ed) and pass the pointer as a uintptr to cWasmerInstanceContextDataSet?

This would reduce some overhead and complexity.

@AdamSLevy
Copy link
Contributor Author

@losfair it's possible I'm misunderstanding your suggestion, but that sounds to me like it would be passing a Go pointer, which may point to something that contains other Go pointers, across the CGo FFI, which would cause a runtime panic and is what this PR is attempting to avoid.

@losfair
Copy link

losfair commented Nov 18, 2019

@AdamSLevy CGo checks are not applied on uintptr since it's just a trivial integer type while unsafe.Pointer is not.

@AdamSLevy
Copy link
Contributor Author

AdamSLevy commented Nov 18, 2019

In that case it would be much simpler. I will test the uintptr approach and report back.

AdamSLevy added a commit to AdamSLevy/go-ext-wasm that referenced this pull request Nov 18, 2019
Previously the given unsafe.Pointer to user data was passed directly
across the CGo FFI resulting in a panic for any reference types or types
that included any reference types or other Go pointers.

This commit avoids a panic by casting the unsafe.Pointer to a uintptr,
which is not analyzed by the runtime. In order for compatability with
the existing CGo API and bridge code, which expects (void*), a *uintptr
is passed. The memory for the user provided unsafe.Pointer and the
*uintptr is cached in the instance to protect it from garbage
collection.

The tests are expanded to ensure that reference types do not cause
panics.

re wasmerio#44 wasmerio#83
@AdamSLevy
Copy link
Contributor Author

Closed in favor of #85

@AdamSLevy AdamSLevy closed this Nov 18, 2019
AdamSLevy added a commit to AdamSLevy/go-ext-wasm that referenced this pull request Dec 3, 2019
Previously an uintptr to user data was passed across the CGo FFI which
would become invalid if any stack frame occurred. This commit avoids
this by never passing any pointers across the CGo FFI. A registry map is
used instead to keep Go data on the Go side, and only an int index into
the map is passed across to the C side.

fix wasmerio#93
re wasmerio#44 wasmerio#85 wasmerio#83
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 component-runtime About the Wasm runtime 🎉 enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants