-
-
Notifications
You must be signed in to change notification settings - Fork 415
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
Array.from_cpointer with CPointer.create violates memory safety #3668
Comments
I genuinely thought that In the docs in Mare I even explained that this is the reason why it must be But you're right - in Pony it returns a This would be a breaking change, but I believe it must return |
What value is there in creating an array that you only have a tag reference to? |
I think the point was that Pointer.create would return a tag, and Array.from_cpointer would remain unchanged and return ref. A Pointer[T] ref should grant you the capability to read and write anywhere within the corresponding allocation, which a null point definitely does not grant |
ah, thanks for the clarification @jasoncarr0 |
If someone wants to working on fixing this, they'll probably run into the fact that Array and String internally rely on being able to create a The |
I've taken a stab at this. There's one issue with the
Both of these cases follow the same pattern: passing a NULL pointer to a C function, which fills it with data. This pointer is then used to create a string or array using To get around this limitation, an option is to create the String or Array on the pony side, and use |
The tricky thing about this is that we're not really passing a pointer to a C function to fill with data - we're passing the address of the stack memory of the pointer so that the pointer itself will be replaced on the C side. This is really the crux of the issue. We start with an invalid pointer (which therefore must be And I've actually seen other examples in Zulip of users who are dealing with a particular C API that works like this, but they can't call it from Pony because of this problem. So we're faced with two options to resolve this ticket:
Path 2️⃣ has the disadvantage that it will only work for fixing the standard library, and any users who want to do something like this will need to write their own C shims around the FFI library they want to wrap. Path 1️⃣ has the disadvantage of having to design a special feature and syntax that won't be used very often, which will need to go through RFC. With that in mind, I suggest we take path 2️⃣ for now and consider path 1️⃣ in the future depending on the level of user frustration with the status quo (leaving the potential frustrated users to drive the RFC process). |
Interestingly enough, So we need to find an efficient approach to get these two filled pointers out from the C side. I have a few ideas rattling around, but I'm not sure which one is the most efficient. For the case of |
Some other options:
|
We discussed on today's sync call that we like approach 3️⃣ the best. To be more specific, we want to change This closes the safety hole, still behaves in a not-surprising way, and won't break any code that works today. Great idea, @jasoncarr0! @ergl - does this change to the approach make sense? |
@jemc Yes, I think it makes sense. If I understand point 3 correctly, the default Pointer constructor will still be Also, you're right that I misunderstood the original code. I tried my approach of constructing a string on the pony side but I couldn't get it to work, now I know why! |
Array's methods and Array.from_cpointer basically trust the user outright; but we can make a null pointer publicly with Pointer.create, and generally blow up
https://stdlib.ponylang.org/builtin-Pointer/#create
https://stdlib.ponylang.org/builtin-Array/#from_cpointer
The text was updated successfully, but these errors were encountered: