diff options
-rw-r--r-- | src/H5MM.c | 47 | ||||
-rw-r--r-- | src/H5MMprivate.h | 1 | ||||
-rw-r--r-- | src/H5private.h | 3 | ||||
-rw-r--r-- | src/H5system.c | 44 | ||||
-rw-r--r-- | src/H5win32defs.h | 9 | ||||
-rw-r--r-- | src/uthash.h | 45 | ||||
-rw-r--r-- | test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/Makefile.am | 2 | ||||
-rw-r--r-- | test/testhdf5.c | 1 | ||||
-rw-r--r-- | test/testhdf5.h | 2 | ||||
-rw-r--r-- | test/th5_system.c | 90 |
11 files changed, 215 insertions, 30 deletions
@@ -503,6 +503,53 @@ done: } /* end H5MM_strdup() */ /*------------------------------------------------------------------------- + * Function: H5MM_strndup + * + * Purpose: Duplicates a string, including memory allocation, but only + * copies at most `n` bytes from the string to be duplicated. + * If the string to be duplicated is longer than `n`, only `n` + * bytes are copied and a terminating null byte is added. + * NULL is NOT an acceptable value for the input string. + * + * If the string to be duplicated is the NULL pointer, then + * an error will be raised. + * + * Return: Success: Pointer to a new string + * Failure: NULL + *------------------------------------------------------------------------- + */ +char * +H5MM_strndup(const char *s, size_t n) +{ +#if defined H5_MEMORY_ALLOC_SANITY_CHECK + size_t len; +#endif + char *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) + + if (!s) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL string not allowed"); + +#if defined H5_MEMORY_ALLOC_SANITY_CHECK + for (len = 0; len < n && s[len] != '\0'; len++) + ; + + if (NULL == (ret_value = H5MM_malloc(len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + H5MM_memcpy(ret_value, s, len); + ret_value[len] = '\0'; +#else + if (NULL == (ret_value = HDstrndup(s, n))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "string duplication failed"); +#endif + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MM_strndup() */ + +/*------------------------------------------------------------------------- * Function: H5MM_xfree * * Purpose: Just like free(3) except null pointers are allowed as diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h index 10e536d..1eedce5 100644 --- a/src/H5MMprivate.h +++ b/src/H5MMprivate.h @@ -43,6 +43,7 @@ H5_DLL void *H5MM_calloc(size_t size); 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); +H5_DLL char *H5MM_strndup(const char *s, size_t n); H5_DLL void *H5MM_xfree(void *mem); H5_DLL void *H5MM_xfree_const(const void *mem); H5_DLL void *H5MM_memcpy(void *dest, const void *src, size_t n); diff --git a/src/H5private.h b/src/H5private.h index 9e6be7e..12be702 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1367,6 +1367,9 @@ H5_DLL H5_ATTR_CONST int Nflock(int fd, int operation); #ifndef HDstrncpy #define HDstrncpy(X, Y, Z) strncpy(X, Y, Z) #endif +#ifndef HDstrndup +#define HDstrndup(S, N) strndup(S, N) +#endif #ifndef HDstrpbrk #define HDstrpbrk(X, Y) strpbrk(X, Y) #endif diff --git a/src/H5system.c b/src/H5system.c index 08a039b..6e55545 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -918,6 +918,50 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5_expand_windows_env_vars() */ + +/*------------------------------------------------------------------------- + * Function: H5_strndup + * + * Purpose: Similar to strndup() for use on Windows. Allocates a new + * string and copies at most `n` bytes from the original + * string into the new string. If the original string is + * longer than `n`, only `n` bytes are copied from the + * original string. In either case, the string being returned + * is guaranteed to be terminated with a null byte. + * + * The returned pointer is allocated by H5MM_malloc in this + * routine and must be freed by the caller with H5MM_free or + * H5MM_xfree. + * + * Return: Pointer to copied string on success + * NULL on failure + * + *------------------------------------------------------------------------- + */ +char * +H5_strndup(const char *s, size_t n) +{ + size_t len; + char *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + if (!s) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "string cannot be NULL") + + for (len = 0; len < n && s[len] != '\0'; len++) + ; + + if (NULL == (ret_value = H5MM_malloc(len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't allocate buffer for string") + + H5MM_memcpy(ret_value, s, len); + ret_value[len] = '\0'; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + #endif /* H5_HAVE_WIN32_API */ /* Global variables */ diff --git a/src/H5win32defs.h b/src/H5win32defs.h index 659adf1..e0ec3c3 100644 --- a/src/H5win32defs.h +++ b/src/H5win32defs.h @@ -17,13 +17,6 @@ * */ -/* _MSC_VER = 193x VS2022 - * _MSC_VER = 192x VS2019 - * _MSC_VER = 191x VS2017 - * _MSC_VER = 1900 VS2015 - * _MSC_VER = 1800 VS2013 - * _MSC_VER = 1700 VS2012 - */ #ifdef H5_HAVE_WIN32_API /* __int64 is the correct type for the st_size field of the _stati64 struct. @@ -83,6 +76,7 @@ struct timezone { #define HDstat(S, B) _stati64(S, B) #define HDstrcasecmp(A, B) _stricmp(A, B) #define HDstrdup(S) _strdup(S) +#define HDstrndup(S, N) H5_strndup(S, N) #define HDstrtok_r(X, Y, Z) strtok_s(X, Y, Z) #define HDtzset() _tzset() #define HDunlink(S) _unlink(S) @@ -104,6 +98,7 @@ H5_DLL wchar_t *H5_get_utf16_str(const char *s); H5_DLL int Wopen_utf8(const char *path, int oflag, ...); H5_DLL int Wremove_utf8(const char *path); H5_DLL int H5_get_win32_times(H5_timevals_t *tvs); +H5_DLL char *H5_strndup(const char *s, size_t n); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/uthash.h b/src/uthash.h index ecf512d..b1e5cbb 100644 --- a/src/uthash.h +++ b/src/uthash.h @@ -699,28 +699,29 @@ typedef unsigned char uint8_t; hashv += (unsigned)(keylen); \ switch (_hj_k) { \ case 11: \ - hashv += ((unsigned)_hj_key[10] << 24); /* FALLTHROUGH */ \ - case 10: \ - hashv += ((unsigned)_hj_key[9] << 16); /* FALLTHROUGH */ \ - case 9: \ - hashv += ((unsigned)_hj_key[8] << 8); /* FALLTHROUGH */ \ - case 8: \ - _hj_j += ((unsigned)_hj_key[7] << 24); /* FALLTHROUGH */ \ - case 7: \ - _hj_j += ((unsigned)_hj_key[6] << 16); /* FALLTHROUGH */ \ - case 6: \ - _hj_j += ((unsigned)_hj_key[5] << 8); /* FALLTHROUGH */ \ - case 5: \ - _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ - case 4: \ - _hj_i += ((unsigned)_hj_key[3] << 24); /* FALLTHROUGH */ \ - case 3: \ - _hj_i += ((unsigned)_hj_key[2] << 16); /* FALLTHROUGH */ \ - case 2: \ - _hj_i += ((unsigned)_hj_key[1] << 8); /* FALLTHROUGH */ \ - case 1: \ - _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ - default:; \ + hashv += ((unsigned)_hj_key[10] << 24); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 10 : hashv += ((unsigned)_hj_key[9] << 16); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 9 : hashv += ((unsigned)_hj_key[8] << 8); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 8 : _hj_j += ((unsigned)_hj_key[7] << 24); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 7 : _hj_j += ((unsigned)_hj_key[6] << 16); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 6 : _hj_j += ((unsigned)_hj_key[5] << 8); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 5 : _hj_j += _hj_key[4]; \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 4 : _hj_i += ((unsigned)_hj_key[3] << 24); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 3 : _hj_i += ((unsigned)_hj_key[2] << 16); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 2 : _hj_i += ((unsigned)_hj_key[1] << 8); \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + case 1 : _hj_i += _hj_key[0]; \ + H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \ + default:; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ } while (0) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e7f9e86..3dc9ef0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,6 +184,7 @@ set (testhdf5_SOURCES ${HDF5_TEST_SOURCE_DIR}/tattr.c ${HDF5_TEST_SOURCE_DIR}/tchecksum.c ${HDF5_TEST_SOURCE_DIR}/tconfig.c + ${HDF5_TEST_SOURCE_DIR}/th5_system.c ${HDF5_TEST_SOURCE_DIR}/tcoords.c ${HDF5_TEST_SOURCE_DIR}/tfile.c ${HDF5_TEST_SOURCE_DIR}/tgenprop.c diff --git a/test/Makefile.am b/test/Makefile.am index 95d9e4f..551c695 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -214,7 +214,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ - tgenprop.c th5o.c th5s.c tcoords.c tid.c titerate.c tmeta.c tmisc.c \ + tgenprop.c th5o.c th5s.c th5_system.c tcoords.c tid.c titerate.c tmeta.c tmisc.c \ trefer.c trefstr.c tselect.c tskiplist.c tsohm.c ttime.c tunicode.c \ tvlstr.c tvltypes.c diff --git a/test/testhdf5.c b/test/testhdf5.c index 587d916..e4d5c3e 100644 --- a/test/testhdf5.c +++ b/test/testhdf5.c @@ -42,6 +42,7 @@ main(int argc, char *argv[]) /* Tests are generally arranged from least to most complexity... */ AddTest("config", test_configure, cleanup_configure, "Configure definitions", NULL); + AddTest("h5system", test_h5_system, cleanup_h5_system, "H5system routines", NULL); AddTest("metadata", test_metadata, cleanup_metadata, "Encoding/decoding metadata", NULL); AddTest("checksum", test_checksum, cleanup_checksum, "Checksum algorithm", NULL); AddTest("skiplist", test_skiplist, NULL, "Skip Lists", NULL); diff --git a/test/testhdf5.h b/test/testhdf5.h index 8abe890..eb2d464 100644 --- a/test/testhdf5.h +++ b/test/testhdf5.h @@ -219,6 +219,7 @@ void test_iterate(void); void test_array(void); void test_genprop(void); void test_configure(void); +void test_h5_system(void); void test_misc(void); void test_ids(void); void test_skiplist(void); @@ -242,6 +243,7 @@ void cleanup_iterate(void); void cleanup_array(void); void cleanup_genprop(void); void cleanup_configure(void); +void cleanup_h5_system(void); void cleanup_sohm(void); void cleanup_misc(void); void cleanup_unicode(void); diff --git a/test/th5_system.c b/test/th5_system.c new file mode 100644 index 0000000..e25e4a0 --- /dev/null +++ b/test/th5_system.c @@ -0,0 +1,90 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5_SYSTEM_TEST_PATH_MAX 4096 + +/*********************************************************** + * + * Test program: th5_system + * + * Testing for the routines available in H5system.c + * + *************************************************************/ + +#include "testhdf5.h" + +#include "H5MMprivate.h" + +static void +test_h5_strndup(void) +{ +#ifdef H5_HAVE_WIN32_API + const char *const teststr = "myteststring"; + char *str = NULL; + + MESSAGE(5, ("Testing H5_strndup\n")); + + /* Check that H5_strndup fails for a NULL string pointer */ + H5E_BEGIN_TRY + { + str = H5_strndup(NULL, 20); + } + H5E_END_TRY + CHECK_PTR_NULL(str, "H5_strndup with NULL string pointer"); + H5Eclear2(H5E_DEFAULT); + + /* Check that H5_strndup correctly performs a 0-byte copy */ + str = H5_strndup(teststr, 0); + CHECK_PTR(str, "H5_strndup for 0-byte copy"); + if (str) + VERIFY_STR(str, "", "comparing H5_strndup for 0-byte copy to empty string"); + str = H5MM_xfree(str); + + /* Check that H5_strndup correctly performs partial copies */ + str = H5_strndup(teststr, 6); + CHECK_PTR(str, "H5_strndup for partial copy"); + if (str) + VERIFY_STR(str, "mytest", "comparing H5_strndup for partial copy to partial string"); + str = H5MM_xfree(str); + + /* Check that H5_strndup correctly performs identical copies */ + str = H5_strndup(teststr, HDstrlen(teststr)); + CHECK_PTR(str, "H5_strndup for identical copy"); + if (str) + VERIFY_STR(str, teststr, "comparing H5_strndup for identical copy to original string"); + str = H5MM_xfree(str); + + /* + * Check that H5_strndup correctly performs copies when + * `n` is greater than the original string + */ + str = H5_strndup(teststr, HDstrlen(teststr) + 2); + CHECK_PTR(str, "H5_strndup for larger 'n'"); + if (str) + VERIFY_STR(str, teststr, "comparing H5_strndup with larger 'n' value to original string"); + str = H5MM_xfree(str); +#endif /* H5_HAVE_WIN32_API */ +} + +void +test_h5_system(void) +{ + MESSAGE(5, ("Testing H5system routines\n")); + + test_h5_strndup(); +} + +void +cleanup_h5_system(void) +{ + /* Nothing to cleanup yet */ +} |