-
Notifications
You must be signed in to change notification settings - Fork 144
Use safer r_memcpy()
and r_memset()
everywhere
#1797
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
Use safer r_memcpy()
and r_memset()
everywhere
#1797
Conversation
Makes sense to me. Linking this discussion which also has relevant insights: Maybe also worth noting the other, much subtler segfault we observed (in an old version of Bioconductor's {IRanges}): SEXP lengths;
int upper_run;
int *lengths_elt = INTEGER(lengths);
upper_run = *lengths_elt; One might hope this would "just work" for length-0 SEXP unless |
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.
ugh
Hm, maybe this can be reverted in favor of just using R's own https://stat.ethz.ch/pipermail/r-devel/2025-April/083995.html |
Isn't it bad to do |
Hm I see what you mean, however, I confirm that just using #include <R_ext/RS.h>
Memcpy(p_out, p_x, cpy_size) resolves my original issue with |
I think the synthesis is thus: |
Per usual, mildly horrifying C behavior // value of x doesn't change
y = sizeof(x++); but that does seem to work in our favor here |
I think I'm still slightly happier with And for scalars like But in general it does seem like |
FWIW that does get caught by a stingy compiler
Works for me. I had a look at switching to |
Closes #1793 (in favor of this more holistic approach)
See also r-lib/vctrs#1968, but here's the TLDR below:
R 4.5.0 enables
CATCH_ZERO_LENGTH_ACCESS
here:https://github.com/r-devel/r-svn/blob/9976c3d7f08c754593d01ba8380afb6be803dde2/src/main/memory.c#L4137-L4150
That means
REAL()
and friends now return an invalid pointer of(void *) 1
on 0-length R objects. I am not sure what it was returning before.This does not prevent us from calling
REAL()
on 0-length R objects. i.e. code like this is fine and safe:It's only if we try and use
p_x
that we may get in trouble on some platforms, like what @MichaelChirico reported. For example, with:In a sane world, these would be safe because C should handle "if the size is 0, do nothing". But on some platforms it can detect that
p_x
is invalid memory, and we get yelled at. The most ergonomic solution for this is to implement "if the size is 0, do nothing" ourselves throughr_memcpy()
andr_memset()
helpers, which is what I've done here. I've used them everywhere (even on memory not necessarily owned by R) except in the vendored xxhash code (which looks to be safe anyways).