diff --git a/src/dogroups.c b/src/dogroups.c index 944cb315d7..5fafa67ac4 100644 --- a/src/dogroups.c +++ b/src/dogroups.c @@ -535,6 +535,11 @@ SEXP growVector(SEXP x, const R_len_t newlen) if (isNull(x)) error(_("growVector passed NULL")); PROTECT(newx = allocVector(TYPEOF(x), newlen)); // TO DO: R_realloc(?) here? if (newlen < len) len=newlen; // i.e. shrink + if (!len) { // cannot memcpy invalid pointer, #6819 + keepattr(newx, x); + UNPROTECT(1); + return newx; + } switch (TYPEOF(x)) { case RAWSXP: memcpy(RAW(newx), RAW(x), len*SIZEOF(x)); break; case LGLSXP: memcpy(LOGICAL(newx), LOGICAL(x), len*SIZEOF(x)); break; diff --git a/src/utils.c b/src/utils.c index 37bae07f3a..7c886f5e23 100644 --- a/src/utils.c +++ b/src/utils.c @@ -222,6 +222,14 @@ SEXP copyAsPlain(SEXP x) { } const int64_t n = XLENGTH(x); SEXP ans = PROTECT(allocVector(TYPEOF(x), n)); + // aside: unlike R's duplicate we do not copy truelength here; important for dogroups.c which uses negative truelenth to mark its specials + if (ALTREP(ans)) + internal_error(__func__, "copyAsPlain returning ALTREP for type '%s'", type2char(TYPEOF(x))); // # nocov + if (!n) { // cannot memcpy invalid pointer, #6819 + DUPLICATE_ATTRIB(ans, x); + UNPROTECT(1); + return ans; + } switch (TYPEOF(x)) { case RAWSXP: memcpy(RAW(ans), RAW(x), n*sizeof(Rbyte)); @@ -250,9 +258,6 @@ SEXP copyAsPlain(SEXP x) { internal_error(__func__, "type '%s' not supported in %s", type2char(TYPEOF(x)), "copyAsPlain()"); // # nocov } DUPLICATE_ATTRIB(ans, x); - // aside: unlike R's duplicate we do not copy truelength here; important for dogroups.c which uses negative truelenth to mark its specials - if (ALTREP(ans)) - internal_error(__func__, "copyAsPlain returning ALTREP for type '%s'", type2char(TYPEOF(x))); // # nocov UNPROTECT(1); return ans; }