From 0497e80b5017f0292a3232cfec4e268f9776d137 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 8 Nov 2003 10:32:53 -0500 Subject: [svn-r7829] Purpose: Bug fix & code cleanup Description: Allowing the library to call malloc with a size of 0 bytes causes problems for some users, so we check for allocations of 0 bytes and disallow them now. Cleaned up some code which could call malloc with 0 size. Changed some code calling HDmalloc directly to call H5MM_malloc(), which allows us to check for 0 sized allocations. Platforms tested: FreeBSD 4.9 (sleipnir) too minor to require h5committest --- configure | 61 ------------------------------ configure.in | 24 ------------ src/H5D.c | 29 ++++++++------- src/H5E.c | 4 +- src/H5FP.c | 2 +- src/H5FPserver.c | 10 ++--- src/H5MM.c | 67 +++++++++++++++++++++++++++++++++ src/H5MMprivate.h | 11 +++--- src/H5config.h.in | 4 -- test/hyperslab.c | 109 +++++++++++++++++++----------------------------------- test/istore.c | 25 ++++++------- test/tconfig.c | 42 --------------------- 12 files changed, 148 insertions(+), 240 deletions(-) diff --git a/configure b/configure index 7808a00..af3e6e0 100755 --- a/configure +++ b/configure @@ -30994,67 +30994,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -echo "$as_me:$LINENO: checking if malloc of zero bytes returns valid pointer" >&5 -echo $ECHO_N "checking if malloc of zero bytes returns valid pointer... $ECHO_C" >&6 -if test "${hdf5_cv_malloc_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5 -echo "$as_me: error: cannot run test program while cross compiling" >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -#include "confdefs.h" - -#if STDC_HEADERS -#include -#endif - -int main(void) -{ - exit(malloc (0) ? 0 : 1); -} - -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - hdf5_cv_malloc_works=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 -( exit $ac_status ) -hdf5_cv_malloc_works=no -fi -rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi - - -if test ${hdf5_cv_malloc_works} = "yes"; then - -cat >>confdefs.h <<\_ACEOF -#define MALLOC_WORKS 1 -_ACEOF - - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - echo "$as_me:$LINENO: checking Threads support system scope" >&5 echo $ECHO_N "checking Threads support system scope... $ECHO_C" >&6 if test "${hdf5_cv_system_scope_threads+set}" = set; then diff --git a/configure.in b/configure.in index da311a3..a2d7067 100644 --- a/configure.in +++ b/configure.in @@ -1697,30 +1697,6 @@ AC_DEFINE_UNQUOTED([PRINTF_LL_WIDTH], ["$hdf5_cv_printf_ll"], [Width for printf() for type \`long long' or \`__int64', use \`ll']) dnl ---------------------------------------------------------------------- -dnl Check if malloc(0) returns valid pointer -dnl -AC_MSG_CHECKING([if malloc of zero bytes returns valid pointer]) -AC_CACHE_VAL([hdf5_cv_malloc_works], -[AC_TRY_RUN([ -#if STDC_HEADERS -#include -#endif - -int main(void) -{ - exit(malloc (0) ? 0 : 1); -} -], [hdf5_cv_malloc_works=yes], [hdf5_cv_malloc_works=no],)]) - -if test ${hdf5_cv_malloc_works} = "yes"; then - AC_DEFINE([MALLOC_WORKS], [1], - [Define if your system's \`malloc' function returns a valid pointer for 0-byte allocations.]) - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -dnl ---------------------------------------------------------------------- dnl Check if pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) dnl is supported on this system dnl diff --git a/src/H5D.c b/src/H5D.c index a384a99..eedce9c 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -3419,19 +3419,22 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id) if((num_dsets=H5F_get_obj_count(f, H5F_OBJ_DATASET))<0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset count") - H5_CHECK_OVERFLOW(num_dsets,int,size_t); - if(NULL==(id_list=H5MM_malloc((size_t)num_dsets*sizeof(hid_t)))) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate memory for ID list") - if(H5F_get_obj_ids(f, H5F_OBJ_DATASET, -1, id_list)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset ID list") - for(j=0; jlayout.type==H5D_COMPACT && dataset->layout.dirty) - if(H5O_modify(&(dataset->ent), H5O_LAYOUT_ID, 0, 0, 1, &(dataset->layout), dxpl_id)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") - dataset->layout.dirty = FALSE; - } + /* Check for something to do */ + if(num_dsets>0) { + H5_CHECK_OVERFLOW(num_dsets,int,size_t); + if(NULL==(id_list=H5MM_malloc((size_t)num_dsets*sizeof(hid_t)))) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate memory for ID list") + if(H5F_get_obj_ids(f, H5F_OBJ_DATASET, -1, id_list)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset ID list") + for(j=0; jlayout.type==H5D_COMPACT && dataset->layout.dirty) + if(H5O_modify(&(dataset->ent), H5O_LAYOUT_ID, 0, 0, 1, &(dataset->layout), dxpl_id)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") + dataset->layout.dirty = FALSE; + } + } /* end if */ done: if(id_list!=NULL) diff --git a/src/H5E.c b/src/H5E.c index 6ca84e9..76aad91 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -780,7 +780,7 @@ H5Eget_major(H5E_major_t maj) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a major one"); /* Don't know who is going to free it */ - msg_str = (char*)HDmalloc((++size)*sizeof(char)); + msg_str = (char*)H5MM_malloc((++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") @@ -830,7 +830,7 @@ H5Eget_minor(H5E_minor_t min) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a minor one"); /* Don't know who is going to free it */ - msg_str = (char*)HDmalloc((++size)*sizeof(char)); + msg_str = (char*)H5MM_malloc((++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") diff --git a/src/H5FP.c b/src/H5FP.c index 77383ee..a0062e1 100644 --- a/src/H5FP.c +++ b/src/H5FP.c @@ -317,7 +317,7 @@ H5FP_read_metadata(char **mdata, int len, int from) * There is metadata associated with this request. Get it as a * string (requires another read). */ - if ((*mdata = (char *)HDmalloc((size_t)len + 1)) == NULL) + if ((*mdata = (char *)H5MM_malloc((size_t)len + 1)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "out of memory"); HDmemset(*mdata, 0, (size_t)len + 1); diff --git a/src/H5FPserver.c b/src/H5FPserver.c index 06ac060..55ae3b3 100644 --- a/src/H5FPserver.c +++ b/src/H5FPserver.c @@ -350,7 +350,7 @@ H5FP_new_object_lock(hobj_ref_t oid, unsigned rank, H5FP_obj_t obj_type, if (MPI_Comm_size(H5FP_SAP_COMM, &comm_size) != MPI_SUCCESS) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, NULL, "MPI_Comm_size failed"); - if ((ret_value = (H5FP_object_lock *)HDmalloc(sizeof(H5FP_object_lock))) == NULL) + if ((ret_value = (H5FP_object_lock *)H5MM_malloc(sizeof(H5FP_object_lock))) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "out of memory"); if ((ret_value->num_locks = (unsigned char *)HDcalloc(comm_size, 1)) == NULL) { @@ -505,7 +505,7 @@ H5FP_new_file_mod_node(unsigned UNUSED rank, H5FD_mem_t mem_type, FUNC_ENTER_NOINIT(H5FP_new_file_mod_node); - if ((ret_value = (H5FP_mdata_mod *)HDmalloc(sizeof(H5FP_mdata_mod))) == NULL) + if ((ret_value = (H5FP_mdata_mod *)H5MM_malloc(sizeof(H5FP_mdata_mod))) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "out of memory"); ret_value->mem_type = mem_type; @@ -624,7 +624,7 @@ H5FP_new_file_info_node(unsigned file_id) FUNC_ENTER_NOINIT(H5FP_new_file_info_node); - if ((ret_value = (H5FP_file_info *)HDmalloc(sizeof(H5FP_file_info))) == NULL) + if ((ret_value = (H5FP_file_info *)H5MM_malloc(sizeof(H5FP_file_info))) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "out of memory"); ret_value->file_id = file_id; @@ -965,7 +965,7 @@ H5FP_sap_handle_lock_request(H5FP_request_t *req) FUNC_ENTER_NOINIT(H5FP_sap_handle_lock_request); - if ((oids = (struct lock_group *)HDmalloc(list_size * + if ((oids = (struct lock_group *)H5MM_malloc(list_size * sizeof(struct lock_group))) == NULL) { exit_state = H5FP_STATUS_OOM; HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "out of memory"); @@ -1171,7 +1171,7 @@ H5FP_sap_handle_release_lock_request(H5FP_request_t *req) FUNC_ENTER_NOINIT(H5FP_sap_handle_release_lock_request); - if ((oids = (struct release_group *)HDmalloc(list_size * + if ((oids = (struct release_group *)H5MM_malloc(list_size * sizeof(struct release_group))) == NULL) { exit_state = H5FP_STATUS_OOM; HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "out of memory"); diff --git a/src/H5MM.c b/src/H5MM.c index 371f292..9701bb9 100644 --- a/src/H5MM.c +++ b/src/H5MM.c @@ -33,6 +33,73 @@ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL +#ifndef NDEBUG + +/*------------------------------------------------------------------------- + * Function: H5MM_malloc + * + * Purpose: Just like the POSIX version of malloc(3). This routine + * specifically checks for allocations of 0 bytes and fails + * in that case. This routine is not called when NDEBUG is + * defined. + * + * Return: Success: Ptr to new memory + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Nov 8 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_malloc(size_t size) +{ + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5MM_malloc); + + assert(size); + + FUNC_LEAVE_NOAPI(HDmalloc(size)); +} /* end H5MM_malloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5MM_calloc + * + * Purpose: Similar to the POSIX version of calloc(3), except this routine + * just takes a 'size' parameter. This routine + * specifically checks for allocations of 0 bytes and fails + * in that case. This routine is not called when NDEBUG is + * defined. + * + * Return: Success: Ptr to new memory + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Nov 8 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_calloc(size_t size) +{ + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5MM_calloc); + + assert(size); + + FUNC_LEAVE_NOAPI(HDcalloc(1,size)); +} /* end H5MM_calloc() */ +#endif /* NDEBUG */ + /*------------------------------------------------------------------------- * Function: H5MM_realloc diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h index 54dfbfb..9aadd36 100644 --- a/src/H5MMprivate.h +++ b/src/H5MMprivate.h @@ -32,18 +32,19 @@ /* Private headers needed by this file */ #include "H5private.h" -#ifdef H5_MALLOC_WORKS +#ifdef NDEBUG #define H5MM_malloc(Z) HDmalloc(Z) #define H5MM_calloc(Z) HDcalloc(1,Z) -#else /* H5_MALLOC_WORKS */ -#define H5MM_malloc(Z) HDmalloc(MAX(1,Z)) -#define H5MM_calloc(Z) HDcalloc(1,MAX(1,Z)) -#endif /* H5_MALLOC_WORKS */ +#endif /* NDEBUG */ #define H5MM_free(Z) HDfree(Z) /* * Library prototypes... */ +#ifndef NDEBUG +H5_DLL void *H5MM_malloc(size_t size); +H5_DLL void *H5MM_calloc(size_t size); +#endif /* NDEBUG */ H5_DLL void *H5MM_realloc(void *mem, size_t size); H5_DLL char *H5MM_xstrdup(const char *s); H5_DLL char *H5MM_strdup(const char *s); diff --git a/src/H5config.h.in b/src/H5config.h.in index ded57d6..20ea728 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -349,10 +349,6 @@ /* Define if `__tm_gmtoff' is a member of `struct tm' */ #undef HAVE___TM_GMTOFF -/* Define if your system's `malloc' function returns a valid pointer for - 0-byte allocations. */ -#undef MALLOC_WORKS - /* Define if your system's `MPI_File_set_size' function works for files over 2GB. */ #undef MPI_FILE_SET_SIZE_BIG diff --git a/test/hyperslab.c b/test/hyperslab.c index 70ee3a5..556d2f0 100644 --- a/test/hyperslab.c +++ b/test/hyperslab.c @@ -24,7 +24,6 @@ #include "h5test.h" #include "H5private.h" #include "H5Eprivate.h" -#include "H5MMprivate.h" #include "H5Vprivate.h" #define TEST_SMALL 0x0001 @@ -130,7 +129,7 @@ print_ref(size_t nx, size_t ny, size_t nz) { uint8_t *array; - array = H5MM_calloc(nx*ny*nz*sizeof(uint8_t)); + array = HDcalloc(nx*ny*nz,sizeof(uint8_t)); printf("Reference array:\n"); init_full(array, nx, ny, nz); @@ -193,7 +192,7 @@ test_fill(size_t nx, size_t ny, size_t nz, fflush(stdout); /* Allocate array */ - dst = H5MM_calloc(nx*ny*nz); + dst = HDcalloc(1,nx*ny*nz); init_full(dst, nx, ny, nz); for (i = 0; i < nx; i += di) { @@ -287,11 +286,11 @@ test_fill(size_t nx, size_t ny, size_t nz, } } puts(" PASSED"); - H5MM_xfree(dst); + HDfree(dst); return SUCCEED; error: - H5MM_xfree(dst); + HDfree(dst); return FAIL; } @@ -397,8 +396,8 @@ test_copy(int mode, /* * Allocate arrays */ - src = H5MM_calloc(nx*ny*nz); - dst = H5MM_calloc(nx*ny*nz); + src = HDcalloc(1,nx*ny*nz); + dst = HDcalloc(1,nx*ny*nz); init_full(src, nx, ny, nz); for (i=0; i