diff --git a/src/drivers/common/mem_alloc.c b/src/drivers/common/mem_alloc.c index 56f98bb7c..279dd44b4 100644 --- a/src/drivers/common/mem_alloc.c +++ b/src/drivers/common/mem_alloc.c @@ -25,6 +25,14 @@ #include #include #include /* strcpy(), strlen() */ + +#ifdef HAVE_STDINT_H +#include /*PTRDIFF_MAX */ +#endif +#ifndef PTRDIFF_MAX +#define PTRDIFF_MAX SIZE_MAX +#endif + #include /* EINVAL */ #include @@ -189,11 +197,28 @@ void *NCI_Malloc_fn(size_t size, const char *func, const char *filename) { - void *buf = malloc(size); + void *buf; + + /* Many C library implementations, particularly those designed to work with + * GCC and Clang, limit single malloc allocations to PTRDIFF_MAX - 1 bytes. + * ptrdiff_t is a signed integer type used for the difference between two + * pointers, and PTRDIFF_MAX is its maximum value. This limitation exists + * because some compiler optimizations and internal library operations may + * rely on pointer differences being representable within ptrdiff_t. + */ + if (size > PTRDIFF_MAX - 1) { + fprintf(stderr, "NCI_Malloc(%zd) failed in file %s func %s line %d\n", + size, filename, func, lineno); + return NULL; + } - if (size > 0 && buf == NULL) - fprintf(stderr, "malloc(%zd) failed in file %s func %s line %d\n", + buf = malloc(size); + + if (size > 0 && buf == NULL) { + fprintf(stderr, "NCI_Malloc(%zd) failed in file %s func %s line %d\n", size, filename, func, lineno); + return NULL; + } #ifdef PNC_MALLOC_TRACE ncmpii_add_mem_entry(buf, size, lineno, func, filename); @@ -216,16 +241,25 @@ void *NCI_Strdup_fn(const char *src, if (src == NULL) return NULL; - len = strlen(src); - buf = malloc(len + 1); + len = strlen(src) + 1; + + if (len > PTRDIFF_MAX - 1) { + fprintf(stderr, "NCI_Strdup(%zd) failed in file %s func %s line %d\n", + len, filename, func, lineno); + return NULL; + } + + buf = malloc(len); - if (len >= 0 && buf == NULL) - fprintf(stderr, "malloc(%zd) failed in file %s func %s line %d\n", + if (buf == NULL) { + fprintf(stderr, "NCI_Strdup(%zd) failed in file %s func %s line %d\n", len, filename, func, lineno); + return NULL; + } - if (len > 0) memcpy(buf, src, len); + memcpy(buf, src, len - 1); - ((char*)buf)[len] = '\0'; + ((char*)buf)[len - 1] = '\0'; #ifdef PNC_MALLOC_TRACE ncmpii_add_mem_entry(buf, len, lineno, func, filename); @@ -246,11 +280,22 @@ void *NCI_Calloc_fn(size_t nelem, const char *func, const char *filename) { - void *buf = calloc(nelem, elsize); + void *buf; - if (nelem > 0 && buf == NULL) - fprintf(stderr, "calloc(%zd, %zd) failed in file %s func %s line %d\n", + if (nelem * elsize > PTRDIFF_MAX - 1) { + fprintf(stderr, "NCI_Calloc(%zd, %zd) failed in file %s func %s line %d\n", nelem, elsize, filename, func, lineno); + return NULL; + } + + /* calloc() accepts zero size, to allow free() to be called later */ + buf = calloc(nelem, elsize); + + if (nelem > 0 && buf == NULL) { + fprintf(stderr, "NCI_Calloc(%zd, %zd) failed in file %s func %s line %d\n", + nelem, elsize, filename, func, lineno); + return NULL; + } #ifdef PNC_MALLOC_TRACE ncmpii_add_mem_entry(buf, nelem * elsize, lineno, func, filename); @@ -277,6 +322,12 @@ void *NCI_Realloc_fn(void *ptr, { void *buf; + if (size > PTRDIFF_MAX - 1) { + fprintf(stderr, "NCI_Realloc(_, %zd) failed in file %s func %s line %d\n", + size, filename, func, lineno); + return NULL; + } + if (ptr == NULL) return NCI_Malloc_fn(size, lineno, func, filename); if (size == 0) { @@ -285,15 +336,19 @@ void *NCI_Realloc_fn(void *ptr, } #ifdef PNC_MALLOC_TRACE - if (ncmpii_del_mem_entry(ptr) != 0) - fprintf(stderr, "realloc failed in file %s func %s line %d\n", - filename, func, lineno); + if (ncmpii_del_mem_entry(ptr) != 0) { + fprintf(stderr, "NCI_Realloc(_, %zd) failed in file %s func %s line %d\n", + size, filename, func, lineno); + return NULL; + } #endif buf = (void *) realloc(ptr, size); - if (buf == NULL) - fprintf(stderr, "realloc failed in file %s func %s line %d\n", - filename, func, lineno); + if (buf == NULL) { + fprintf(stderr, "NCI_Realloc(_, %zd) failed in file %s func %s line %d\n", + size, filename, func, lineno); + return NULL; + } #ifdef PNC_MALLOC_TRACE ncmpii_add_mem_entry(buf, size, lineno, func, filename); @@ -319,7 +374,7 @@ void NCI_Free_fn(void *ptr, #ifdef PNC_MALLOC_TRACE if (ncmpii_del_mem_entry(ptr) != 0) - fprintf(stderr, "free failed in file %s func %s line %d\n", + fprintf(stderr, "NCI_Free failed in file %s func %s line %d\n", filename, func, lineno); #endif diff --git a/src/drivers/include/common.h b/src/drivers/include/common.h index 8e3d30aa3..ee69fb854 100644 --- a/src/drivers/include/common.h +++ b/src/drivers/include/common.h @@ -73,19 +73,11 @@ extern void NCI_Free_fn(void *ptr, const int lineno, const char *func, const char *filename); -#if defined(PNETCDF_DEBUG) || defined(PNC_MALLOC_TRACE) #define NCI_Malloc(a) NCI_Malloc_fn(a,__LINE__,__func__,__FILE__) #define NCI_Strdup(a) NCI_Strdup_fn(a,__LINE__,__func__,__FILE__) #define NCI_Calloc(a,b) NCI_Calloc_fn(a,b,__LINE__,__func__,__FILE__) #define NCI_Realloc(a,b) NCI_Realloc_fn(a,b,__LINE__,__func__,__FILE__) #define NCI_Free(a) NCI_Free_fn(a,__LINE__,__func__,__FILE__) -#else -#define NCI_Malloc(a) malloc(a) -#define NCI_Strdup(a) strdup(a) -#define NCI_Calloc(a,b) calloc(a,b) -#define NCI_Realloc(a,b) realloc(a,b) -#define NCI_Free(a) free(a) -#endif extern int ncmpii_inq_malloc_size(size_t *size);