Skip to content

Commit

Permalink
Bring strndup changes from develop (#3437)
Browse files Browse the repository at this point in the history
  • Loading branch information
derobins authored Aug 28, 2023
1 parent 8f9098b commit 11f3fee
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 30 deletions.
47 changes: 47 additions & 0 deletions src/H5MM.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,53 @@ H5MM_strdup(const char *s)
FUNC_LEAVE_NOAPI(ret_value)
} /* 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
*
Expand Down
1 change: 1 addition & 0 deletions src/H5MMprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/H5private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions src/H5system.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,50 @@ H5_expand_windows_env_vars(char **env_var)

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 */
Expand Down
9 changes: 2 additions & 7 deletions src/H5win32defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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 */
Expand Down
45 changes: 23 additions & 22 deletions src/uthash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions test/testhdf5.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions test/testhdf5.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
90 changes: 90 additions & 0 deletions test/th5_system.c
Original file line number Diff line number Diff line change
@@ -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 *
* [email protected]. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#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 */
}

0 comments on commit 11f3fee

Please sign in to comment.