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

Address memory issues when copying empty enums #3088

Merged
merged 2 commits into from Jun 12, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions release_docs/RELEASE.txt
Expand Up @@ -228,6 +228,17 @@ Bug Fixes since HDF5-1.14.0 release
===================================
Library
-------
- Fixed a potential bug when copying empty enum datatypes

Copying an empty enum datatype (including implicitly, as when an enum
is a part of a compound datatype) would fail in an assert in debug
mode and could fail in release mode depending on how the platform
handles undefined behavior regarding size 0 memory allocations and
using memcpy with a NULL src pointer.

The library is now more more careful about using memory operations when
copying empty enum datatypes and will not error or raise an assert.

- Added an AAPL check to H5Acreate

A check was added to H5Acreate to ensure that a failure is correctly
Expand Down
37 changes: 22 additions & 15 deletions src/H5T.c
Expand Up @@ -3623,21 +3623,28 @@ H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo
* of each new member with copied values. That is, H5T_copy() is a
* deep copy.
*/
if (NULL == (new_dt->shared->u.enumer.name =
H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char *))))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam name array memory allocation failed")
if (NULL == (new_dt->shared->u.enumer.value =
H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
"enam value array memory allocation failed")
H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
for (i = 0; i < new_dt->shared->u.enumer.nmembs; i++) {
if (NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i])))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
"can't copy string for enum value's name")
new_dt->shared->u.enumer.name[i] = s;
} /* end for */
if (old_dt->shared->u.enumer.nalloc > 0) {
if (NULL == (new_dt->shared->u.enumer.name =
H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char *))))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
"enam name array memory allocation failed")
if (NULL == (new_dt->shared->u.enumer.value =
H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
"enam value array memory allocation failed")
H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
for (i = 0; i < new_dt->shared->u.enumer.nmembs; i++) {
if (NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i])))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
"can't copy string for enum value's name")
new_dt->shared->u.enumer.name[i] = s;
}
}
else {
/* Empty enum */
HDmemset(&new_dt->shared->u.enumer, 0, sizeof(H5T_enum_t));
}
lkurz marked this conversation as resolved.
Show resolved Hide resolved
break;

case H5T_VLEN:
Expand Down
6 changes: 4 additions & 2 deletions src/H5Tcompound.c
Expand Up @@ -469,10 +469,12 @@ H5T__insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)

/* Add member to end of member array */
idx = parent->shared->u.compnd.nmembs;
parent->shared->u.compnd.memb[idx].name = H5MM_xstrdup(name);
parent->shared->u.compnd.memb[idx].offset = offset;
parent->shared->u.compnd.memb[idx].size = total_size;
parent->shared->u.compnd.memb[idx].type = H5T_copy(member, H5T_COPY_ALL);
if (NULL == (parent->shared->u.compnd.memb[idx].name = H5MM_xstrdup(name)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't duplicate name string")
if (NULL == (parent->shared->u.compnd.memb[idx].type = H5T_copy(member, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "couldn't copy datatype")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little extra defensive programming here...


parent->shared->u.compnd.sorted = H5T_SORT_NONE;
parent->shared->u.compnd.nmembs++;
Expand Down