diff --git a/src/extra/graphapp/bitmaps.c b/src/extra/graphapp/bitmaps.c index 665513f1689..5d639cda134 100644 --- a/src/extra/graphapp/bitmaps.c +++ b/src/extra/graphapp/bitmaps.c @@ -211,7 +211,8 @@ bitmap imagetobitmap(image img) data[i+2] = getred(colour); } } - else memcpy(data, pixel32, 4*height*width); + else if (height && width) + memcpy(data, pixel32, 4*height*width); /* Create the bitmap from the DIB data. Could also use CreateDIBsection */ diff --git a/src/extra/xdr/xdr_mem.c b/src/extra/xdr/xdr_mem.c index 2d8038fdd23..b9d82d0dad6 100644 --- a/src/extra/xdr/xdr_mem.c +++ b/src/extra/xdr/xdr_mem.c @@ -168,7 +168,7 @@ xdrmem_getbytes( if ((xdrs->x_handy -= len) < 0) return (FALSE); - memcpy(addr, xdrs->x_private, len); + if (len) memcpy(addr, xdrs->x_private, len); xdrs->x_private += len; return (TRUE); } @@ -182,7 +182,7 @@ xdrmem_putbytes( if ((xdrs->x_handy -= len) < 0) return (FALSE); - memcpy(xdrs->x_private, addr, len); + if (len) memcpy(xdrs->x_private, addr, len); xdrs->x_private += len; return (TRUE); } diff --git a/src/gnuwin32/console.c b/src/gnuwin32/console.c index f1088463396..ecabb46288e 100644 --- a/src/gnuwin32/console.c +++ b/src/gnuwin32/console.c @@ -2000,7 +2000,8 @@ int consolereads(control c, const char *prompt, char *buf, int len, segment is empty (should not happen) or internal segment of line of same length as buffer */ - memcpy(buf, segment, slen); + if (slen) + memcpy(buf, segment, slen); free(segment); buf[slen] = '\0'; return res; diff --git a/src/gnuwin32/getline/getline.c b/src/gnuwin32/getline/getline.c index 40088284796..01608b5f2ab 100644 --- a/src/gnuwin32/getline/getline.c +++ b/src/gnuwin32/getline/getline.c @@ -447,9 +447,10 @@ gl_realloc(void *ptr, int olditems, int newitems, size_t itemsize) void *res; if (!(res = realloc(ptr, newitems * itemsize))) gl_error("\n*** Error: getline(): not enough memory.\n"); - memset(((char *)res) + olditems * itemsize, - 0, - (newitems - olditems) * itemsize); + if (newitems > olditems) + memset(((char *)res) + olditems * itemsize, + 0, + (newitems - olditems) * itemsize); return res; } @@ -1556,11 +1557,10 @@ hist_save(const char *p) { char *s = 0; int len = strlen(p); - char *nl = strchr(p, '\n'); - if (nl) { + if (len && p[len - 1] == '\n') { if ((s = (char *) malloc(len)) != 0) { - memcpy(s, p, len-1); + memcpy(s, p, len-1); s[len-1] = 0; } } else { diff --git a/src/gnuwin32/system.c b/src/gnuwin32/system.c index d9806d7a949..63cf6d6d2ca 100644 --- a/src/gnuwin32/system.c +++ b/src/gnuwin32/system.c @@ -419,7 +419,8 @@ CharReadConsole(const char *prompt, unsigned char *buf, int len, int tocopy = remaining; if (tocopy > len - 1) tocopy = len - 1; - memcpy(buf, line + offset, tocopy); + if (tocopy) + memcpy(buf, line + offset, tocopy); buf[tocopy] = '\0'; remaining -= tocopy; offset += tocopy; diff --git a/src/include/R_ext/RS.h b/src/include/R_ext/RS.h index 15735b57630..ecef1836cdc 100644 --- a/src/include/R_ext/RS.h +++ b/src/include/R_ext/RS.h @@ -48,6 +48,8 @@ extern "C" { extern void *R_chk_calloc(R_SIZE_T, R_SIZE_T); extern void *R_chk_realloc(void *, R_SIZE_T); extern void R_chk_free(void *); +extern void *R_chk_memcpy(void *, const void *, R_SIZE_T); +extern void *R_chk_memset(void *, int, R_SIZE_T); #ifndef STRICT_R_HEADERS /* S-PLUS 3.x but not 5.x NULLed the pointer in Free. @@ -64,10 +66,10 @@ extern void R_chk_free(void *); #define R_Free(p) (R_chk_free( (void *)(p) ), (p) = NULL) /* Nowadays API: undocumented until 4.1.2: widely used. */ -#define Memcpy(p,q,n) memcpy( p, q, (R_SIZE_T)(n) * sizeof(*p) ) +#define Memcpy(p,q,n) R_chk_memcpy( p, q, (R_SIZE_T)(n) * sizeof(*p) ) /* Nowadays API: added for 3.0.0 but undocumented until 4.1.2. */ -#define Memzero(p,n) memset(p, 0, (R_SIZE_T)(n) * sizeof(*p)) +#define Memzero(p,n) R_chk_memset(p, 0, (R_SIZE_T)(n) * sizeof(*p)) /* API: Added in R 2.6.0 */ #define CallocCharBuf(n) (char *) R_chk_calloc(((R_SIZE_T)(n))+1, sizeof(char)) diff --git a/src/library/graphics/src/stem.c b/src/library/graphics/src/stem.c index 55fe7778125..a6ed856667b 100644 --- a/src/library/graphics/src/stem.c +++ b/src/library/graphics/src/stem.c @@ -180,7 +180,8 @@ C_bincount(double *x, R_xlen_t n, double *breaks, R_xlen_t nb, int *count, R_xlen_t i, lo, hi, nb1 = nb - 1, new; // for(i = 0; i < nb1; i++) count[i] = 0; - memset(count, 0, nb1 * sizeof(int)); + if (nb1) + memset(count, 0, nb1 * sizeof(int)); for(i = 0 ; i < n ; i++) if(R_FINITE(x[i])) { // left in as a precaution diff --git a/src/library/stats/src/HoltWinters.c b/src/library/stats/src/HoltWinters.c index 6241fbfa08f..ca87cce4e31 100644 --- a/src/library/stats/src/HoltWinters.c +++ b/src/library/stats/src/HoltWinters.c @@ -1,6 +1,6 @@ /* R : A Computer Language for Statistical Data Analysis * - * Copyright (C) 2003-7 The R Core Team + * Copyright (C) 2003-24 The R Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +54,7 @@ void HoltWinters (double *x, /* copy start values to the beginning of the vectors */ level[0] = *a; if (*dotrend == 1) trend[0] = *b; - if (*doseasonal == 1) memcpy(season, s, *period * sizeof(double)); + if (*doseasonal == 1 && *period) memcpy(season, s, *period * sizeof(double)); for (i = *start_time - 1; i < *xl; i++) { /* indices for period i */ diff --git a/src/library/stats/src/ansari.c b/src/library/stats/src/ansari.c index 7aed745c405..d45fa27d786 100644 --- a/src/library/stats/src/ansari.c +++ b/src/library/stats/src/ansari.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1999-2016 The R Core Team + * Copyright (C) 1999-2024 The R Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,10 +35,12 @@ w_init(int m, int n) double ***w; w = (double ***) R_alloc(m + 1, sizeof(double **)); - memset(w, '\0', (m+1) * sizeof(double**)); + if (m+1) + memset(w, '\0', (m+1) * sizeof(double**)); for (i = 0; i <= m; i++) { w[i] = (double**) R_alloc(n + 1, sizeof(double *)); - memset(w[i], '\0', (n+1) * sizeof(double*)); + if (n+1) + memset(w[i], '\0', (n+1) * sizeof(double*)); } return(w); } @@ -57,7 +59,8 @@ cansari(int k, int m, int n, double ***w) if (w[m][n] == 0) { w[m][n] = (double *) R_alloc(u + 1, sizeof(double)); - memset(w[m][n], '\0', (u + 1) * sizeof(double)); + if (u+1) + memset(w[m][n], '\0', (u + 1) * sizeof(double)); for (i = 0; i <= u; i++) w[m][n][i] = -1; } diff --git a/src/library/stats/src/kendall.c b/src/library/stats/src/kendall.c index b80da5a5bb2..df2e878a260 100644 --- a/src/library/stats/src/kendall.c +++ b/src/library/stats/src/kendall.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1999-2016 The R Core Team. + * Copyright (C) 1999-2024 The R Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,8 @@ ckendall(int k, int n, double **w) if ((k < 0) || (k > u)) return(0); if (w[n] == 0) { w[n] = (double *) R_alloc(u + 1, sizeof(double)); - memset(w[n], '\0', sizeof(double) * (u+1)); + if (u+1) + memset(w[n], '\0', sizeof(double) * (u+1)); for (i = 0; i <= u; i++) w[n][i] = -1; } if (w[n][k] < 0) { @@ -82,7 +83,8 @@ pkendall(int len, double *Q, double *P, int n) double **w; w = (double **) R_alloc(n + 1, sizeof(double *)); - memset(w, '\0', sizeof(double*) * (n+1)); + if (n+1) + memset(w, '\0', sizeof(double*) * (n+1)); for (i = 0; i < len; i++) { q = floor(Q[i] + 1e-7); diff --git a/src/library/stats/src/model.c b/src/library/stats/src/model.c index bf76dd5bc99..47a72b57d0a 100644 --- a/src/library/stats/src/model.c +++ b/src/library/stats/src/model.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1997--2023 The R Core Team + * Copyright (C) 1997--2024 The R Core Team * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka * * This program is free software; you can redistribute it and/or modify @@ -1274,7 +1274,8 @@ static void ExtractVars(SEXP formula) static SEXP AllocTerm(void) // ( nwords) { SEXP term = allocVector(INTSXP, nwords); // caller must PROTECT - memset(INTEGER(term), 0, nwords * sizeof(int)); + if (nwords) + memset(INTEGER(term), 0, nwords * sizeof(int)); return term; } diff --git a/src/library/stats/src/port.c b/src/library/stats/src/port.c index 3a569352d72..331ede01220 100644 --- a/src/library/stats/src/port.c +++ b/src/library/stats/src/port.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2005-2022 The R Core Team. + * Copyright (C) 2005-2024 The R Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -236,7 +236,8 @@ double F77_NAME(dv2nrm)(int *n, const double x[]) void F77_NAME(dv7cpy)(int *n, double dest[], const double src[]) { /* Was memcpy, but overlaps seen */ - memmove(dest, src, *n * sizeof(double)); + if (*n) + memmove(dest, src, *n * sizeof(double)); } /* dv7ipr... applies forward permutation to vector. */ diff --git a/src/library/stats/src/rWishart.c b/src/library/stats/src/rWishart.c index 98fa6aef1f1..f71c7723a9b 100644 --- a/src/library/stats/src/rWishart.c +++ b/src/library/stats/src/rWishart.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2012-2022 The R Core Team + * Copyright (C) 2012-2024 The R Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,7 +92,8 @@ rWishart(SEXP ns, SEXP nuP, SEXP scal) scCp = R_Calloc(psqr, double); Memcpy(scCp, REAL(scal), psqr); - memset(tmp, 0, psqr * sizeof(double)); + if (psqr) + memset(tmp, 0, psqr * sizeof(double)); F77_CALL(dpotrf)("U", &(dims[0]), scCp, &(dims[0]), &info FCONE); // LAPACK if (info) error(_("'scal' matrix is not positive-definite")); diff --git a/src/library/tools/src/gramRd.c b/src/library/tools/src/gramRd.c index 44f3b0fdbf5..f37375b9882 100644 --- a/src/library/tools/src/gramRd.c +++ b/src/library/tools/src/gramRd.c @@ -3208,7 +3208,8 @@ static SEXP xxusermacro(SEXP macro, SEXP args, YYLTYPE *lloc) SEXP stri = CAR(si); if (!isComment(stri)) { int nc = LENGTH(STRING_ELT(stri, 0)); - memcpy(str + offset, CHAR(STRING_ELT(stri, 0)), nc); + if (nc) + memcpy(str + offset, CHAR(STRING_ELT(stri, 0)), nc); offset += nc; } } diff --git a/src/library/tools/src/gramRd.y b/src/library/tools/src/gramRd.y index 288c3586888..61fafc66cdb 100644 --- a/src/library/tools/src/gramRd.y +++ b/src/library/tools/src/gramRd.y @@ -670,7 +670,8 @@ static SEXP xxusermacro(SEXP macro, SEXP args, YYLTYPE *lloc) SEXP stri = CAR(si); if (!isComment(stri)) { int nc = LENGTH(STRING_ELT(stri, 0)); - memcpy(str + offset, CHAR(STRING_ELT(stri, 0)), nc); + if (nc) + memcpy(str + offset, CHAR(STRING_ELT(stri, 0)), nc); offset += nc; } } diff --git a/src/main/altclasses.c b/src/main/altclasses.c index ce2015a3abd..da75234138c 100644 --- a/src/main/altclasses.c +++ b/src/main/altclasses.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2016--2023 The R Core Team + * Copyright (C) 2016--2024 The R Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -690,7 +690,8 @@ static R_INLINE SEXP ExpandDeferredStringElt(SEXP x, R_xlen_t i) if (val == R_NilValue) { R_xlen_t n = XLENGTH(x); val = allocVector(STRSXP, n); - memset(STDVEC_DATAPTR(val), 0, n * sizeof(SEXP)); + if (n) + memset(STDVEC_DATAPTR(val), 0, n * sizeof(SEXP)); SET_DEFERRED_STRING_EXPANDED(x, val); } diff --git a/src/main/apply.c b/src/main/apply.c index 8056911094a..36cf2cd848d 100644 --- a/src/main/apply.c +++ b/src/main/apply.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2000-2023 The R Core Team + * Copyright (C) 2000-2024 The R Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -206,7 +206,7 @@ attribute_hidden SEXP do_vapply(SEXP call, SEXP op, SEXP args, SEXP rho) case STRSXP: SET_STRING_ELT(ans, i, STRING_ELT(val, 0)); break; case VECSXP: SET_VECTOR_ELT(ans, i, VECTOR_ELT(val, 0)); break; } - } else { // commonLen > 1 (typically, or == 0) : + } else if (commonLen) { // commonLen > 1 switch (commonType) { case REALSXP: memcpy(REAL(ans) + common_len_offset, diff --git a/src/main/connections.c b/src/main/connections.c index c0d12a5ad58..867b1cb6c83 100644 --- a/src/main/connections.c +++ b/src/main/connections.c @@ -305,7 +305,8 @@ static size_t buff_set_len(Rconnection con, size_t len) { buff = (unsigned char *)malloc(sizeof(unsigned char) * len); if (con->buff) { - memcpy(buff, con->buff + con->buff_pos, unread_len); + if (unread_len) + memcpy(buff, con->buff + con->buff_pos, unread_len); free(con->buff); } @@ -2695,7 +2696,8 @@ static size_t clp_write(const void *ptr, size_t size, size_t nitems, /* copy byte-by-byte */ int space = this->len - this->pos; used = (space < len) ? space : len; - memcpy(this->buff + this->pos, ptr, used); + if (used) + memcpy(this->buff + this->pos, ptr, used); this->pos += used; #endif @@ -2956,7 +2958,8 @@ static void raw_resize(Rrawconn this, size_t needed) if (needed > 8192) nalloc = (size_t)(1.2*(double)needed); /* 20% over-allocation */ else while(nalloc < needed) nalloc *= 2; /* use powers of 2 if small */ PROTECT(tmp = allocVector(RAWSXP, nalloc)); - memcpy(RAW(tmp), RAW(this->data), this->nbytes); + if (this->nbytes) + memcpy(RAW(tmp), RAW(this->data), this->nbytes); R_ReleaseObject(this->data); this->data = tmp; R_PreserveObject(this->data); @@ -2974,7 +2977,8 @@ static size_t raw_write(const void *ptr, size_t size, size_t nitems, /* resize may fail, when this will give an error */ if(bytes >= freespace) raw_resize(this, bytes + this->pos); /* the source just might be this raw vector */ - memmove(RAW(this->data) + this->pos, ptr, bytes); + if (bytes) + memmove(RAW(this->data) + this->pos, ptr, bytes); this->pos += bytes; if(this->nbytes < this->pos) this->nbytes = this->pos; return nitems; @@ -3143,7 +3147,8 @@ attribute_hidden SEXP do_rawconvalue(SEXP call, SEXP op, SEXP args, SEXP env) error(_("'con' is not an output rawConnection")); this = con->private; ans = allocVector(RAWSXP, this->nbytes); /* later, use TRUELENGTH? */ - memcpy(RAW(ans), RAW(this->data), this->nbytes); + if (this->nbytes) + memcpy(RAW(ans), RAW(this->data), this->nbytes); return ans; } @@ -4294,7 +4299,7 @@ rawRead(char *p, int size, R_xlen_t n, Rbyte *bytes, R_xlen_t nbytes, R_xlen_t * m = n; if (m > avail) m = avail; if (m > 0) { - memcpy(p, bytes + *(np), m*size); + if (size) memcpy(p, bytes + *(np), m*size); *np += m*size; } return m; @@ -4857,7 +4862,8 @@ readFixedString(Rconnection con, int len, int useBytes, Rboolean *warnOnNul) *p = '\0'; } else { buf = (char *) R_alloc(len+1, sizeof(char)); - memset(buf, 0, len+1); + if (len+1) + memset(buf, 0, len+1); m = (int) con->read(buf, sizeof(char), len, con); if(len && !m) return R_NilValue; buf[m] = '\0'; @@ -4904,7 +4910,8 @@ rawFixedString(Rbyte *bytes, int len, int nbytes, int *np, int useBytes) } else { /* no terminator */ buf = R_chk_calloc(len + 1, 1); - memcpy(buf, bytes + (*np), len); + if (len) + memcpy(buf, bytes + (*np), len); *np += len; res = mkCharLenCE(buf, len, CE_NATIVE); R_Free(buf); @@ -5098,8 +5105,10 @@ attribute_hidden SEXP do_writechar(SEXP call, SEXP op, SEXP args, SEXP env) if(len > LENGTH(si)) { warning(_("writeChar: more bytes requested than are in the string - will zero-pad")); } - memset(buf, '\0', len + slen); - memcpy(buf, CHAR(si), len); + if (len + slen) + memset(buf, '\0', len + slen); + if (len) + memcpy(buf, CHAR(si), len); if (usesep) { strcpy(buf + len, ssep); len += slen; @@ -5138,7 +5147,8 @@ attribute_hidden SEXP do_writechar(SEXP call, SEXP op, SEXP args, SEXP env) } else lenb = len; } - memset(buf, '\0', lenb + slen); + if (lenb + slen) + memset(buf, '\0', lenb + slen); strncpy(buf, s, lenb); if (usesep) { strcpy(buf + lenb, ssep); @@ -6244,7 +6254,8 @@ SEXP R_decompress1(SEXP in, Rboolean *err) return R_NilValue; } SEXP ans = allocVector(RAWSXP, actual_out); - memcpy(RAW(ans), buf, actual_out); + if (actual_out) + memcpy(RAW(ans), buf, actual_out); vmaxset(vmax); return ans; } @@ -6291,7 +6302,8 @@ SEXP R_decompress1(SEXP in, Rboolean *err) return R_NilValue; } SEXP ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); vmaxset(vmax); return ans; } @@ -6322,7 +6334,8 @@ SEXP R_compress2(SEXP in) if (res != BZ_OK || outlen > inlen) { outlen = inlen; buf[4] = '0'; - memcpy(buf+5, (char *)RAW(in), inlen); + if (inlen) + memcpy(buf+5, (char *)RAW(in), inlen); } ans = allocVector(RAWSXP, outlen + 5); memcpy(RAW(ans), buf, outlen + 5); @@ -6369,7 +6382,8 @@ SEXP R_decompress2(SEXP in, Rboolean *err) return R_NilValue; } ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); vmaxset(vmax); return ans; } @@ -6616,7 +6630,8 @@ SEXP R_decompress3(SEXP in, Rboolean *err) return R_NilValue; } ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); vmaxset(vmax); return ans; } @@ -6666,7 +6681,8 @@ do_memCompress(SEXP call, SEXP op, SEXP args, SEXP env) res = compress(buf, &outlen, (Bytef *)RAW(from), inlen); if(res != Z_OK) error("internal error %d in memCompress", res); ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } #endif @@ -6681,7 +6697,8 @@ do_memCompress(SEXP call, SEXP op, SEXP args, SEXP env) inlen, 9, 0, 0); if(res != BZ_OK) error("internal error %d in memCompress", res); ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } case 4: /* xz */ @@ -6716,7 +6733,8 @@ do_memCompress(SEXP call, SEXP op, SEXP args, SEXP env) outlen = (unsigned int)strm.total_out; lzma_end(&strm); ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } default: @@ -6817,7 +6835,8 @@ do_memDecompress(SEXP call, SEXP op, SEXP args, SEXP env) } } ans = allocVector(RAWSXP, actual_out); - memcpy(RAW(ans), buf, actual_out); + if (actual_out) + memcpy(RAW(ans), buf, actual_out); break; } #else @@ -6845,7 +6864,8 @@ do_memDecompress(SEXP call, SEXP op, SEXP args, SEXP env) } ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } #endif @@ -6870,7 +6890,8 @@ do_memDecompress(SEXP call, SEXP op, SEXP args, SEXP env) "type = \"bzip2\""); } ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } case 4: /* xz */ @@ -6924,7 +6945,8 @@ do_memDecompress(SEXP call, SEXP op, SEXP args, SEXP env) outlen = strm.total_out; lzma_end(&strm); ans = allocVector(RAWSXP, outlen); - memcpy(RAW(ans), buf, outlen); + if (outlen) + memcpy(RAW(ans), buf, outlen); break; } // case 5 is "unknown', covered above diff --git a/src/main/dotcode.c b/src/main/dotcode.c index 156807f764e..4c9e8d580ac 100644 --- a/src/main/dotcode.c +++ b/src/main/dotcode.c @@ -1769,12 +1769,12 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) char *ptr = R_alloc(n * sizeof(Rbyte) + 2 * NG, 1); memset(ptr, FILL, n * sizeof(Rbyte) + 2 * NG); ptr += NG; - memcpy(ptr, RAW(s), n); + if (n) memcpy(ptr, RAW(s), n); cargs[na] = (void *) ptr; } else if (MAYBE_REFERENCED(s)) { n = XLENGTH(s); SEXP ss = allocVector(t, n); - memcpy(RAW(ss), RAW(s), n * sizeof(Rbyte)); + if (n) memcpy(RAW(ss), RAW(s), n * sizeof(Rbyte)); SET_VECTOR_ELT(ans, na, ss); cargs[na] = (void*) RAW(ss); #ifdef R_MEMORY_PROFILING @@ -1794,11 +1794,11 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) char *ptr = R_alloc(n * sizeof(int) + 2 * NG, 1); memset(ptr, FILL, n * sizeof(int) + 2 * NG); ptr += NG; - memcpy(ptr, INTEGER(s), n * sizeof(int)); + if (n) memcpy(ptr, INTEGER(s), n * sizeof(int)); cargs[na] = (void*) ptr; } else if (MAYBE_REFERENCED(s)) { SEXP ss = allocVector(t, n); - memcpy(INTEGER(ss), INTEGER(s), n * sizeof(int)); + if (n) memcpy(INTEGER(ss), INTEGER(s), n * sizeof(int)); SET_VECTOR_ELT(ans, na, ss); cargs[na] = (void*) INTEGER(ss); #ifdef R_MEMORY_PROFILING @@ -1824,11 +1824,11 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) char *ptr = R_alloc(n * sizeof(double) + 2 * NG, 1); memset(ptr, FILL, n * sizeof(double) + 2 * NG); ptr += NG; - memcpy(ptr, REAL(s), n * sizeof(double)); + if (n) memcpy(ptr, REAL(s), n * sizeof(double)); cargs[na] = (void*) ptr; } else if (MAYBE_REFERENCED(s)) { SEXP ss = allocVector(t, n); - memcpy(REAL(ss), REAL(s), n * sizeof(double)); + if (n) memcpy(REAL(ss), REAL(s), n * sizeof(double)); SET_VECTOR_ELT(ans, na, ss); cargs[na] = (void*) REAL(ss); #ifdef R_MEMORY_PROFILING @@ -1847,11 +1847,11 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) char *ptr = R_alloc(n * sizeof(Rcomplex) + 2 * NG, 1); memset(ptr, FILL, n * sizeof(Rcomplex) + 2 * NG); ptr += NG; - memcpy(ptr, COMPLEX(s), n * sizeof(Rcomplex)); + if (n) memcpy(ptr, COMPLEX(s), n * sizeof(Rcomplex)); cargs[na] = (void*) ptr; } else if (MAYBE_REFERENCED(s)) { SEXP ss = allocVector(t, n); - memcpy(COMPLEX(ss), COMPLEX(s), n * sizeof(Rcomplex)); + if (n) memcpy(COMPLEX(ss), COMPLEX(s), n * sizeof(Rcomplex)); SET_VECTOR_ELT(ans, na, ss); cargs[na] = (void*) COMPLEX(ss); #ifdef R_MEMORY_PROFILING @@ -2561,7 +2561,7 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) if (copy) { s = allocVector(type, n); unsigned char *ptr = (unsigned char *) p; - memcpy(RAW(s), ptr, n * sizeof(Rbyte)); + if (n) memcpy(RAW(s), ptr, n * sizeof(Rbyte)); ptr += n * sizeof(Rbyte); for (int i = 0; i < NG; i++) if(*ptr++ != FILL) @@ -2580,7 +2580,7 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) if (copy) { s = allocVector(type, n); unsigned char *ptr = (unsigned char *) p; - memcpy(INTEGER(s), ptr, n * sizeof(int)); + if (n) memcpy(INTEGER(s), ptr, n * sizeof(int)); ptr += n * sizeof(int); for (int i = 0; i < NG; i++) if(*ptr++ != FILL) @@ -2634,7 +2634,7 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) REAL(s)[i] = (double) sptr[i]; } else { unsigned char *ptr = (unsigned char *) p; - memcpy(REAL(s), ptr, n * sizeof(double)); + if (n) memcpy(REAL(s), ptr, n * sizeof(double)); ptr += n * sizeof(double); for (int i = 0; i < NG; i++) if(*ptr++ != FILL) @@ -2662,7 +2662,7 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env) if (copy) { s = allocVector(type, n); unsigned char *ptr = (unsigned char *) p; - memcpy(COMPLEX(s), p, n * sizeof(Rcomplex)); + if (n) memcpy(COMPLEX(s), p, n * sizeof(Rcomplex)); ptr += n * sizeof(Rcomplex); for (int i = 0; i < NG; i++) if(*ptr++ != FILL) diff --git a/src/main/duplicate.c b/src/main/duplicate.c index 9c78294a736..a434b4f3741 100644 --- a/src/main/duplicate.c +++ b/src/main/duplicate.c @@ -60,11 +60,11 @@ else { \ R_xlen_t __this; \ type *__to = fun(to), *__from = fun(from); \ - do { \ + while(__n__ > 0) { \ __this = (__n__ < 1000000) ? __n__ : 1000000; \ memcpy(__to, __from, __this * sizeof(type)); \ __n__ -= __this; __to += __this; __from += __this; \ - } while(__n__ > 0); \ + } \ } \ DUPLICATE_ATTRIB(to, from, deep); \ COPY_TRUELENGTH(to, from); \ @@ -76,7 +76,7 @@ PROTECT(from); \ PROTECT(to = allocVector(TYPEOF(from), __n__)); \ if (__n__ == 1) fun(to)[0] = fun(from)[0]; \ - else memcpy(fun(to), fun(from), __n__ * sizeof(type)); \ + else if (__n__) memcpy(fun(to), fun(from), __n__ * sizeof(type)); \ DUPLICATE_ATTRIB(to, from, deep); \ COPY_TRUELENGTH(to, from); \ UNPROTECT(2); \ diff --git a/src/main/envir.c b/src/main/envir.c index 4fabfc209e8..f56e8d9cbaf 100644 --- a/src/main/envir.c +++ b/src/main/envir.c @@ -4318,7 +4318,7 @@ SEXP mkCharLenCE(const char *name, int len, cetype_t enc) representing this string, and EncodeString() is the most comprehensive */ c = allocCharsxp(len); - memcpy(CHAR_RW(c), name, len); + if (len) memcpy(CHAR_RW(c), name, len); switch(enc) { case CE_UTF8: SET_UTF8(c); break; case CE_LATIN1: SET_LATIN1(c); break; @@ -4356,7 +4356,7 @@ SEXP mkCharLenCE(const char *name, int len, cetype_t enc) if (cval == R_NilValue) { /* no cached value; need to allocate one and add to the cache */ PROTECT(cval = allocCharsxp(len)); - memcpy(CHAR_RW(cval), name, len); + if (len) memcpy(CHAR_RW(cval), name, len); switch(enc) { case CE_NATIVE: break; /* don't set encoding */ diff --git a/src/main/eval.c b/src/main/eval.c index 0aa98153e49..d18d211317c 100644 --- a/src/main/eval.c +++ b/src/main/eval.c @@ -8715,6 +8715,8 @@ attribute_hidden SEXP R_bcEncode(SEXP bytes) m = (sizeof(BCODE) + sizeof(int) - 1) / sizeof(int); n = LENGTH(bytes); + if (n == 0) + return R_NilValue; ipc = INTEGER(bytes); v = ipc[0]; diff --git a/src/main/gram.c b/src/main/gram.c index 6ed06dbceb3..672d2f1e9ec 100644 --- a/src/main/gram.c +++ b/src/main/gram.c @@ -5114,7 +5114,8 @@ static SEXP mkStringUTF8(const ucs_t *wcs, int cnt) #endif R_CheckStack2(nb); char s[nb]; - memset(s, 0, nb); /* safety */ + if (nb) + memset(s, 0, nb); /* safety */ // This used to differentiate WC_NOT_UNICODE but not needed wcstoutf8(s, (const wchar_t *)wcs, sizeof(s)); PROTECT(t = allocVector(STRSXP, 1)); diff --git a/src/main/gram.y b/src/main/gram.y index a281ddd7587..85d96bd30e3 100644 --- a/src/main/gram.y +++ b/src/main/gram.y @@ -2805,7 +2805,8 @@ static SEXP mkStringUTF8(const ucs_t *wcs, int cnt) #endif R_CheckStack2(nb); char s[nb]; - memset(s, 0, nb); /* safety */ + if (nb) + memset(s, 0, nb); /* safety */ // This used to differentiate WC_NOT_UNICODE but not needed wcstoutf8(s, (const wchar_t *)wcs, sizeof(s)); PROTECT(t = allocVector(STRSXP, 1)); diff --git a/src/main/memory.c b/src/main/memory.c index 159b9c8f355..fc24b1e07d4 100644 --- a/src/main/memory.c +++ b/src/main/memory.c @@ -2388,10 +2388,11 @@ char *S_realloc(char *p, long new, long old, int size) size_t nold; char *q; /* shrinking is a no-op */ - if(new <= old) return p; // so nnew > 0 below + if(new <= old) return p; // so new > 0 below q = R_alloc((size_t)new, size); nold = (size_t)old * size; - memcpy(q, p, nold); + if (nold) + memcpy(q, p, nold); memset(q + nold, 0, (size_t)new*size - nold); return q; } @@ -3567,6 +3568,16 @@ void R_chk_free(void *ptr) better to be safe here */ } +void *R_chk_memcpy(void *dest, const void *src, size_t n) +{ + return n ? memcpy(dest, src, n) : dest; +} + +void *R_chk_memset(void *s, int c, size_t n) +{ + return n ? memset(s, c, n) : s; +} + /* This code keeps a list of objects which are not assigned to variables but which are required to persist across garbage collections. The objects are registered with R_PreserveObject and deregistered with diff --git a/src/main/platform.c b/src/main/platform.c index dc9ecc50c09..7578855c706 100644 --- a/src/main/platform.c +++ b/src/main/platform.c @@ -1427,7 +1427,8 @@ size_t path_buffer_append(R_StringBuffer *pb, const char *name, size_t len) size_t newlen = len + namelen + 1; if (newlen > pb->bufsize) R_AllocStringBuffer(newlen, pb); - memcpy(pb->data + len, name, namelen); + if (namelen) + memcpy(pb->data + len, name, namelen); pb->data[newlen - 1] = '\0'; #ifdef Unix if (newlen > R_PATH_MAX) @@ -1453,7 +1454,8 @@ Rboolean search_setup(R_StringBuffer *pb, SEXP path, R_DIR **dir, size_t len = strlen(dnp); if (len + 1 > pb->bufsize) R_AllocStringBuffer(len + 1, pb); - memcpy(pb->data, dnp, len); + if (len) + memcpy(pb->data, dnp, len); /* open directory */ pb->data[len] = '\0'; @@ -1696,7 +1698,8 @@ attribute_hidden SEXP do_listdirs(SEXP call, SEXP op, SEXP args, SEXP rho) add_to_ans(&ans, "", &count, &countmax, idx); } else { char *dnp = R_alloc(len + 1, 1); - memcpy(dnp, pb.data, len); + if (len) + memcpy(dnp, pb.data, len); /* remove trailing separator if added by search_setup */ if (added_separator) dnp[len - 1] = '\0'; diff --git a/src/main/radixsort.c b/src/main/radixsort.c index a8282151033..ddacd9881a2 100644 --- a/src/main/radixsort.c +++ b/src/main/radixsort.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2016-2023 The R Core Team + * Copyright (C) 2016-2024 The R Core Team * * Based on code donated from the data.table package * (C) 2006-2015 Matt Dowle and Arun Srinivasan. @@ -321,7 +321,8 @@ static void icount(int *x, int *o, int n) counts[x[i] - xmin] = 0; } } else - memset(counts, 0, (range + 1) * sizeof(int)); + if (range + 1) + memset(counts, 0, (range + 1) * sizeof(int)); return; } diff --git a/src/main/raw.c b/src/main/raw.c index b1ddfaf93f4..67892caaeff 100644 --- a/src/main/raw.c +++ b/src/main/raw.c @@ -451,7 +451,7 @@ attribute_hidden SEXP do_intToUtf8(SEXP call, SEXP op, SEXP args, SEXP env) this = 0x10000 + (hi << 10) + lo; } used = inttomb(buf, this); - memcpy(tmp + len, buf, used); + if (used) memcpy(tmp + len, buf, used); len += used; } PROTECT(ans = allocVector(STRSXP, 1)); diff --git a/src/main/serialize.c b/src/main/serialize.c index a56e1d0b68f..3224f9ee463 100644 --- a/src/main/serialize.c +++ b/src/main/serialize.c @@ -2751,7 +2751,8 @@ static void OutBytesBB(R_outpstream_t stream, void *buf, int length) if (bb->count + length > BCONBUFSIZ) flush_bcon_buffer(bb); if (length <= BCONBUFSIZ) { - memcpy(bb->buf + bb->count, buf, length); + if (length) + memcpy(bb->buf + bb->count, buf, length); bb->count += length; } else if (R_WriteConnection(bb->con, buf, length) != length) @@ -2851,7 +2852,8 @@ static void OutBytesMem(R_outpstream_t stream, void *buf, int length) error(_("serialization is too large to store in a raw vector")); #endif if (needed > mb->size) resize_buffer(mb, needed); - memcpy(mb->buf + mb->count, buf, length); + if (length) + memcpy(mb->buf + mb->count, buf, length); mb->count = needed; } @@ -2868,7 +2870,8 @@ static void InBytesMem(R_inpstream_t stream, void *buf, int length) membuf_t mb = stream->data; if (mb->count + (R_size_t) length > mb->size) error(_("read error")); - memcpy(buf, mb->buf + mb->count, length); + if (length) + memcpy(buf, mb->buf + mb->count, length); mb->count += length; } @@ -2914,7 +2917,8 @@ static SEXP CloseMemOutPStream(R_outpstream_t stream) error(_("serialization is too large to store in a raw vector")); #endif PROTECT(val = allocVector(RAWSXP, mb->count)); - memcpy(RAW(val), mb->buf, mb->count); + if (mb->count) + memcpy(RAW(val), mb->buf, mb->count); free_mem_buffer(mb); UNPROTECT(1); return val; @@ -3120,7 +3124,8 @@ static SEXP readRawFromFile(SEXP file, SEXP key) for (i = 0; i < used; i++) if(names[i] != NULL && strcmp(cfile, names[i]) == 0) {icache = i; break;} if (icache >= 0) { - memcpy(RAW(val), ptr[icache]+offset, len); + if (len) + memcpy(RAW(val), ptr[icache]+offset, len); vmaxset(vmax); return val; } @@ -3158,7 +3163,8 @@ static SEXP readRawFromFile(SEXP file, SEXP key) in = (int) fread(p, 1, filelen, fp); fclose(fp); if (filelen != in) error(_("read failed on %s"), cfile); - memcpy(RAW(val), p+offset, len); + if (len) + memcpy(RAW(val), p+offset, len); } else { if (p) free(p); diff --git a/src/main/subscript.c b/src/main/subscript.c index b2add3d4288..1773c968e0d 100644 --- a/src/main/subscript.c +++ b/src/main/subscript.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1997--2023 The R Core Team + * Copyright (C) 1997--2024 The R Core Team * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka * * This program is free software; you can redistribute it and/or modify @@ -544,7 +544,8 @@ attribute_hidden SEXP strmat2intmat(SEXP s, SEXP dnamelist, SEXP call, SEXP x) SEXP si = PROTECT(allocVector(INTSXP, xlength(s))); dimgets(si, dim); int *psi = INTEGER(si); - memset(psi, 0, XLENGTH(si) * sizeof(int)); + if (XLENGTH(si)) + memset(psi, 0, XLENGTH(si) * sizeof(int)); for (int i = 0; i < nc; i++) { R_xlen_t iNR = i * (R_xlen_t) nr; for (int j = 0; j < nr; j++) @@ -619,7 +620,8 @@ logicalSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call) buf[count++] = (double)(i + 1); }); PROTECT(indx = allocVector(REALSXP, count)); - memcpy(REAL(indx), buf, sizeof(double) * count); + if (count) + memcpy(REAL(indx), buf, sizeof(double) * count); vmaxset(vmax); UNPROTECT(1); return indx; @@ -670,7 +672,8 @@ logicalSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call) buf[count++] = (int)(i + 1); }); PROTECT(indx = allocVector(INTSXP, count)); - memcpy(INTEGER(indx), buf, sizeof(int) * count); + if (count) + memcpy(INTEGER(indx), buf, sizeof(int) * count); vmaxset(vmax); UNPROTECT(1); return indx; diff --git a/src/main/sysutils.c b/src/main/sysutils.c index 2e4f8ec824c..8ef570d8cf0 100644 --- a/src/main/sysutils.c +++ b/src/main/sysutils.c @@ -867,7 +867,8 @@ attribute_hidden SEXP do_iconv(SEXP call, SEXP op, SEXP args, SEXP env) R_AllocStringBuffer(2*cbuff.bufsize, &cbuff); goto top_of_loop; } - memcpy(outbuf, sub, sub_len); + if (sub_len) + memcpy(outbuf, sub, sub_len); outbuf += sub_len; outb -= sub_len; } inbuf++; inb--; @@ -878,7 +879,8 @@ attribute_hidden SEXP do_iconv(SEXP call, SEXP op, SEXP args, SEXP env) if(res != -1 && inb == 0) { size_t nout = cbuff.bufsize - 1 - outb; SEXP el = allocVector(RAWSXP, nout); - memcpy(RAW(el), cbuff.data, nout); + if (nout) + memcpy(RAW(el), cbuff.data, nout); SET_VECTOR_ELT(ans, i, el); } /* otherwise is already NULL */ } else { diff --git a/src/modules/internet/Rhttpd.c b/src/modules/internet/Rhttpd.c index a392e0379c5..033d055dab9 100644 --- a/src/modules/internet/Rhttpd.c +++ b/src/modules/internet/Rhttpd.c @@ -263,7 +263,8 @@ static SEXP collect_buffers(struct buffer *buf) { res = allocVector(RAWSXP, len + buf->length); dst = (char*) RAW(res); while (buf) { - memcpy(dst, buf->data, buf->length); + if (buf->length) + memcpy(dst, buf->data, buf->length); dst += buf->length; buf = buf->next; } @@ -1038,7 +1039,8 @@ static void worker_input_handler(void *data) { /* add "Request-Method: xxx" */ memcpy(c->headers->data + c->headers->length, "Request-Method: ", 16); c->headers->length += 16; - memcpy(c->headers->data + c->headers->length, bol, mend - bol); + if (mend - bol) + memcpy(c->headers->data + c->headers->length, bol, mend - bol); c->headers->length += mend - bol; c->headers->data[c->headers->length++] = '\n'; } @@ -1063,7 +1065,7 @@ static void worker_input_handler(void *data) { if (fits) memcpy(c->headers->data + c->headers->length, bol, fits); if (alloc_buffer(2048, c->headers)) { c->headers = c->headers->next; - memcpy(c->headers->data, bol + fits, l - fits); + if (l - fits) memcpy(c->headers->data, bol + fits, l - fits); c->headers->length = l - fits; c->headers->data[c->headers->length++] = '\n'; } diff --git a/src/modules/internet/sockconn.c b/src/modules/internet/sockconn.c index 94804ca3366..f9699654b3b 100644 --- a/src/modules/internet/sockconn.c +++ b/src/modules/internet/sockconn.c @@ -1,6 +1,6 @@ /* * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2001-2023 The R Core Team. + * Copyright (C) 2001-2024 The R Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -173,7 +173,8 @@ static ssize_t sock_read_helper(Rconnection con, void *ptr, size_t size) n = size; else n = this->pend - this->pstart; - memcpy(ptr, this->pstart, n); + if (n) + memcpy(ptr, this->pstart, n); ptr = ((char *) ptr) + n; this->pstart += n; size -= n;