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

Pass char* to Go and convert with C.GoString, avoiding unsafe use #288

Merged
merged 1 commit into from
Jun 24, 2023

Conversation

ssiegel
Copy link
Contributor

@ssiegel ssiegel commented Jun 11, 2023

Using the char* passed by Mosquitto in a GoString struct is unsafe. The memory it points to is managed by Mosquitto, but Go will keep the pointer around for an indefinite duration, even when Mosquitto might free the memory.

By passing the actual char* to Go, we can use C.GoString to convert it, which copies the bytes into a buffer managed by Go. That way we can use it safely at any time in the future.

Using the char* passed by Mosquitto in a GoString struct is unsafe.
The memory it points to is managed by Mosquitto, but Go will keep the
pointer around for an indefinite duration, even when Mosquitto might
free the memory.

By passing the actual char* to Go, we can use C.GoString to convert it,
which copies the bytes into a buffer managed by Go. That way we can use
it safely at any time in the future.
@ssiegel ssiegel requested a review from iegomez as a code owner June 11, 2023 17:18
@ssiegel
Copy link
Contributor Author

ssiegel commented Jun 11, 2023

I encountered this issue in mosquitto-go-auth-oauth2, which keeps a cache keyed by the username. The cache is used to store access and refresh tokens acquired at login for future queries to the userinfo endpoint. With long lived sessions this cache can become corrupted. It is possible to work around it in mosquitto-go-auth-oauth2 by passing the cache keys through strings.Clone, but fixing it at the source seems to be the correct solution.

@iegomez
Copy link
Owner

iegomez commented Jun 12, 2023

Thanks, @ssiegel, I'll take a look during this week.

GoString go_clientid = {clientid, strlen(clientid)};
GoString go_username = {username, strlen(username)};
GoString go_topic = {topic, strlen(topic)};
GoInt32 go_access = access;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one thing that caught my eye.

Why pass acc directly and accept a C.int on AuthAclCheck instead of defining a GoInt32 as we were doing before?
It's more surprising when you don't give the same treatment to opts_count, also defined as a GoInt32 and passed along to AuthPluginInit, which receives a Go int instead of a C.int.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it really matters technically. I changed this in AuthAclCheck for mostly aesthetical reasons, to consistently have C types as parameters. AuthPluginInit/opts_count is an oversight. Would you prefer to use C.int there as well, or should I revert the acc parameter of AuthAclCheck to GoInt32?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a preference really, was just asking if there was a particular reason to treat them differently.
Since there's not, I think we're good to merge.

Thanks!

@iegomez iegomez merged commit ea7214a into iegomez:master Jun 24, 2023
2 checks passed
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.

None yet

2 participants