Skip to content

Commit 299d44d

Browse files
Avoid memcpy()-ing 0-length vectors (#6820)
* Avoid memcpy()-ing 0-length vectors The C standard (before C23) says that giving invalid pointers, even with length=0, to memcpy() is undefined behaviour. R returns an invalid pointer for vectors of length 0, so avoid calls to memcpy() altogether in such cases. * Use early returns for 0-length cases Co-authored-by: Michael Chirico <[email protected]>
1 parent 6ea929f commit 299d44d

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

src/dogroups.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ SEXP growVector(SEXP x, const R_len_t newlen)
535535
if (isNull(x)) error(_("growVector passed NULL"));
536536
PROTECT(newx = allocVector(TYPEOF(x), newlen)); // TO DO: R_realloc(?) here?
537537
if (newlen < len) len=newlen; // i.e. shrink
538+
if (!len) { // cannot memcpy invalid pointer, #6819
539+
keepattr(newx, x);
540+
UNPROTECT(1);
541+
return newx;
542+
}
538543
switch (TYPEOF(x)) {
539544
case RAWSXP: memcpy(RAW(newx), RAW(x), len*SIZEOF(x)); break;
540545
case LGLSXP: memcpy(LOGICAL(newx), LOGICAL(x), len*SIZEOF(x)); break;

src/utils.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ SEXP copyAsPlain(SEXP x) {
222222
}
223223
const int64_t n = XLENGTH(x);
224224
SEXP ans = PROTECT(allocVector(TYPEOF(x), n));
225+
// aside: unlike R's duplicate we do not copy truelength here; important for dogroups.c which uses negative truelenth to mark its specials
226+
if (ALTREP(ans))
227+
internal_error(__func__, "copyAsPlain returning ALTREP for type '%s'", type2char(TYPEOF(x))); // # nocov
228+
if (!n) { // cannot memcpy invalid pointer, #6819
229+
DUPLICATE_ATTRIB(ans, x);
230+
UNPROTECT(1);
231+
return ans;
232+
}
225233
switch (TYPEOF(x)) {
226234
case RAWSXP:
227235
memcpy(RAW(ans), RAW(x), n*sizeof(Rbyte));
@@ -250,9 +258,6 @@ SEXP copyAsPlain(SEXP x) {
250258
internal_error(__func__, "type '%s' not supported in %s", type2char(TYPEOF(x)), "copyAsPlain()"); // # nocov
251259
}
252260
DUPLICATE_ATTRIB(ans, x);
253-
// aside: unlike R's duplicate we do not copy truelength here; important for dogroups.c which uses negative truelenth to mark its specials
254-
if (ALTREP(ans))
255-
internal_error(__func__, "copyAsPlain returning ALTREP for type '%s'", type2char(TYPEOF(x))); // # nocov
256261
UNPROTECT(1);
257262
return ans;
258263
}

0 commit comments

Comments
 (0)