Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring strndup changes from develop #3437

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 */
}