Audit use of GC.@preserve#391
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #391 +/- ##
==========================================
- Coverage 89.89% 89.86% -0.03%
==========================================
Files 7 7
Lines 1316 1322 +6
==========================================
+ Hits 1183 1188 +5
- Misses 133 134 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Thanks for the PR! I'll take a look. |
| return if codeunit(y) == UInt8 | ||
| x.len == sizeof(y) || return false | ||
| ref = Base.cconvert(Ptr{UInt8}, y) | ||
| cmp = GC.@preserve ref ccall(:memcmp, Cint, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), x.ptr, Base.unsafe_convert(Ptr{UInt8}, ref), x.len) |
There was a problem hiding this comment.
The manual preserve here seems to be exactly equivalent to simply passing y to ccall directly.
|
In each case of an added In perhaps simpler terms, very early in our parsing entrypoints ( |
no this is not the case. (And especially so due to inlining) |
otoh, assuming these are true, it is perfectly valid to ensure the liveness of the object you’ve taken pointer from at the top level and rely on that for all the lower level users, if it is more convenient to do so. However, the only way to guarantee liveness locally outside of a ccall is by using gc preserve. |
Ok, so you're saying if we do a |
|
More complete implementation in #395 |
Fix one use of
GC.@preserveand add TODOs where an invalid pointer escapesGC.@preserve.@quinnj : Retaining a pointer beyond a
GC.@preserveis undefined behaviour in Julia, and I've seen at least one case where it causes a real miscompilation.I've opted not to fix the use of
parsestringin this PR since that's a larger refactoring that you're best equipped to do. But I've tried to find all the places in the codebase where it's used.