From ccb68f709181942106eef92e3f39575add1792e6 Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Tue, 22 Aug 2017 01:36:20 -0500 Subject: Fix for HDFFV-10216 segfault in H5G_node_cmp3 with corrupt h5 file Fix H5HL_offset_into() to return error when offset exceeds heap data block size. Also fix other places that call this routine to detect error return. --- MANIFEST | 2 + src/H5Gent.c | 20 +- src/H5Glink.c | 12 +- src/H5Gnode.c | 748 +++++++++++++++++++++++++------------------------- src/H5Gstab.c | 16 +- src/H5HL.c | 15 +- src/H5Oefl.c | 47 ++-- test/CMakeTests.cmake | 2 + test/Makefile.am | 2 +- test/bad_offset.h5 | Bin 0 -> 3312 bytes test/gen_bad_offset.c | 112 ++++++++ test/tmisc.c | 55 ++++ 12 files changed, 612 insertions(+), 419 deletions(-) create mode 100644 test/bad_offset.h5 create mode 100644 test/gen_bad_offset.c diff --git a/MANIFEST b/MANIFEST index 16900d2..22e7317 100644 --- a/MANIFEST +++ b/MANIFEST @@ -831,6 +831,7 @@ ./test/accum.c ./test/app_ref.c ./test/bad_compound.h5 +./test/bad_offset.h5 ./test/be_data.h5 ./test/be_extlink1.h5 ./test/be_extlink2.h5 @@ -876,6 +877,7 @@ ./test/fixed_idx.h5 ./test/flush1.c ./test/flush2.c +./test/gen_bad_offset.c ./test/gen_bad_ohdr.c ./test/gen_bad_compound.c ./test/gen_bogus.c diff --git a/src/H5Gent.c b/src/H5Gent.c index 05e8b3c..bb6aa38 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -541,8 +541,8 @@ herr_t H5G__ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth, const H5HL_t *heap) { - const char *lval = NULL; - int nested_indent, nested_fwidth; + const char *lval = NULL; + int nested_indent, nested_fwidth; FUNC_ENTER_PACKAGE_NOERR @@ -551,14 +551,14 @@ H5G__ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth, nested_fwidth = MAX(0, fwidth - 3); HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Name offset into private heap:", - (unsigned long) (ent->name_off)); + "Name offset into private heap:", + (unsigned long) (ent->name_off)); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, - "Object header address:", ent->header); + "Object header address:", ent->header); HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Cache info type:"); + "Cache info type:"); switch(ent->type) { case H5G_NOTHING_CACHED: HDfprintf(stream, "Nothing Cached\n"); @@ -581,13 +581,13 @@ H5G__ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth, HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Cached information:"); HDfprintf(stream, "%*s%-*s %lu\n", nested_indent, "", nested_fwidth, - "Link value offset:", - (unsigned long)(ent->cache.slink.lval_offset)); + "Link value offset:", + (unsigned long)(ent->cache.slink.lval_offset)); if(heap) { lval = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset); HDfprintf(stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth, - "Link value:", - lval); + "Link value:", + (lval == NULL) ? "" : lval); } /* end if */ else HDfprintf(stream, "%*s%-*s\n", nested_indent, "", nested_fwidth, "Warning: Invalid heap address given, name not displayed!"); diff --git a/src/H5Glink.c b/src/H5Glink.c index 7b99207..fe49458 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -224,7 +224,9 @@ herr_t H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, const H5G_entry_t *ent, const char *name) { - FUNC_ENTER_PACKAGE_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE /* check arguments */ HDassert(lnk); @@ -243,7 +245,8 @@ H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, if(ent->type == H5G_CACHED_SLINK) { const char *s; /* Pointer to link value */ - s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset); + if((s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset)) == NULL) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link name") HDassert(s); /* Copy the link value */ @@ -260,7 +263,10 @@ H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, lnk->type = H5L_TYPE_HARD; } /* end else */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + if(ret_value < 0 && lnk->name) + H5MM_xfree(lnk->name); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__ent_to_link() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 12e0d5e..7de9ec9 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -13,14 +13,14 @@ /*------------------------------------------------------------------------- * - * Created: H5Gnode.c - * Jun 26 1997 - * Robb Matzke + * Created: H5Gnode.c + * Jun 26 1997 + * Robb Matzke * - * Purpose: Functions for handling symbol table nodes. A - * symbol table node is a small collection of symbol - * table entries. A B-tree usually points to the - * symbol table nodes for any given symbol table. + * Purpose: Functions for handling symbol table nodes. A + * symbol table node is a small collection of symbol + * table entries. A B-tree usually points to the + * symbol table nodes for any given symbol table. * *------------------------------------------------------------------------- */ @@ -35,16 +35,16 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* File access */ -#include "H5FLprivate.h" /* Free Lists */ -#include "H5Gpkg.h" /* Groups */ -#include "H5HLprivate.h" /* Local Heaps */ -#include "H5MFprivate.h" /* File memory management */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5Ppublic.h" /* Property Lists */ +#include "H5private.h" /* Generic Functionsi */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Gpkg.h" /* Groups */ +#include "H5HLprivate.h" /* Local Heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Ppublic.h" /* Property Lists */ /****************/ @@ -77,20 +77,16 @@ typedef struct H5G_node_key_t { /* B-tree callbacks */ static H5RC_t *H5G_node_get_shared(const H5F_t *f, const void *_udata); static herr_t H5G_node_create(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, void *_lt_key, - void *_udata, void *_rt_key, - haddr_t *addr_p/*out*/); + void *_udata, void *_rt_key, haddr_t *addr_p/*out*/); static int H5G_node_cmp2(void *_lt_key, void *_udata, void *_rt_key); static int H5G_node_cmp3(void *_lt_key, void *_udata, void *_rt_key); static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key, - void *_udata); + void *_udata); static H5B_ins_t H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, - hbool_t *lt_key_changed, void *_md_key, - void *_udata, void *_rt_key, - hbool_t *rt_key_changed, - haddr_t *new_node_p/*out*/); + hbool_t *lt_key_changed, void *_md_key, void *_udata, void *_rt_key, + hbool_t *rt_key_changed, haddr_t *new_node_p/*out*/); static H5B_ins_t H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *lt_key, - hbool_t *lt_key_changed, void *udata, - void *rt_key, hbool_t *rt_key_changed); + hbool_t *lt_key_changed, void *udata, void *rt_key, hbool_t *rt_key_changed); static herr_t H5G_node_decode_key(const H5B_shared_t *shared, const uint8_t *raw, void *_key); static herr_t H5G_node_encode_key(const H5B_shared_t *shared, uint8_t *raw, const void *_key); static herr_t H5G_node_debug_key(FILE *stream, int indent, int fwidth, @@ -103,21 +99,21 @@ static herr_t H5G_node_debug_key(FILE *stream, int indent, int fwidth, /* H5G inherits B-tree like properties from H5B */ H5B_class_t H5B_SNODE[1] = {{ - H5B_SNODE_ID, /*id */ - sizeof(H5G_node_key_t), /*sizeof_nkey */ - H5G_node_get_shared, /*get_shared */ - H5G_node_create, /*new */ - H5G_node_cmp2, /*cmp2 */ - H5G_node_cmp3, /*cmp3 */ - H5G_node_found, /*found */ - H5G_node_insert, /*insert */ - TRUE, /*follow min branch? */ - TRUE, /*follow max branch? */ - H5B_RIGHT, /*critical key */ - H5G_node_remove, /*remove */ - H5G_node_decode_key, /*decode */ - H5G_node_encode_key, /*encode */ - H5G_node_debug_key, /*debug */ + H5B_SNODE_ID, /*id */ + sizeof(H5G_node_key_t), /*sizeof_nkey */ + H5G_node_get_shared, /*get_shared */ + H5G_node_create, /*new */ + H5G_node_cmp2, /*cmp2 */ + H5G_node_cmp3, /*cmp3 */ + H5G_node_found, /*found */ + H5G_node_insert, /*insert */ + TRUE, /*follow min branch? */ + TRUE, /*follow max branch? */ + H5B_RIGHT, /*critical key */ + H5G_node_remove, /*remove */ + H5G_node_decode_key, /*decode */ + H5G_node_encode_key, /*encode */ + H5G_node_debug_key /*debug */ }}; /* Declare a free list to manage the H5G_node_t struct */ @@ -138,17 +134,16 @@ H5FL_SEQ_DEFINE(H5G_entry_t); /*------------------------------------------------------------------------- - * Function: H5G_node_get_shared + * Function: H5G_node_get_shared * - * Purpose: Returns the shared B-tree info for the specified UDATA. + * Purpose: Returns the shared B-tree info for the specified UDATA. * - * Return: Success: Pointer to the raw B-tree page for this - file's groups + * Return: Success: Pointer to the raw B-tree page for this file's groups * - * Failure: Can't fail + * Failure: Can't fail * - * Programmer: Robb Matzke - * Wednesday, October 8, 1997 + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 * * Modifications: * @@ -167,22 +162,22 @@ H5G_node_get_shared(const H5F_t *f, const void H5_ATTR_UNUSED *_udata) /*------------------------------------------------------------------------- - * Function: H5G_node_decode_key + * Function: H5G_node_decode_key * - * Purpose: Decodes a raw key into a native key. + * Purpose: Decodes a raw key into a native key. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 8 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 8 1997 * *------------------------------------------------------------------------- */ static herr_t H5G_node_decode_key(const H5B_shared_t *shared, const uint8_t *raw, void *_key) { - H5G_node_key_t *key = (H5G_node_key_t *) _key; + H5G_node_key_t *key = (H5G_node_key_t *) _key; FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -199,13 +194,13 @@ H5G_node_decode_key(const H5B_shared_t *shared, const uint8_t *raw, void *_key) /*------------------------------------------------------------------------- * Function: H5G_node_encode_key * - * Purpose: Encodes a native key into a raw key. + * Purpose: Encodes a native key into a raw key. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 8 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 8 1997 * *------------------------------------------------------------------------- */ @@ -227,13 +222,13 @@ H5G_node_encode_key(const H5B_shared_t *shared, uint8_t *raw, const void *_key) /*------------------------------------------------------------------------- - * Function: H5G_node_debug_key + * Function: H5G_node_debug_key * - * Purpose: Prints a key. + * Purpose: Prints a key. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Friday, February 28, 2003 * *------------------------------------------------------------------------- @@ -242,7 +237,7 @@ static herr_t H5G_node_debug_key(FILE *stream, int indent, int fwidth, const void *_key, const void *_udata) { - const H5G_node_key_t *key = (const H5G_node_key_t *) _key; + const H5G_node_key_t *key = (const H5G_node_key_t *) _key; const H5G_bt_common_t *udata = (const H5G_bt_common_t *) _udata; FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -250,15 +245,15 @@ H5G_node_debug_key(FILE *stream, int indent, int fwidth, const void *_key, HDassert(key); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Heap offset:", - (unsigned)key->offset); + (unsigned)key->offset); if(udata->heap) { const char *s; HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Name:"); - s = (const char *)H5HL_offset_into(udata->heap, key->offset); - HDfprintf(stream, "%s\n", s); + if((s = (const char *)H5HL_offset_into(udata->heap, key->offset)) != NULL) + HDfprintf(stream, "%s\n", s); } /* end if */ else HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Cannot get name; heap address not specified\n"); @@ -270,13 +265,13 @@ H5G_node_debug_key(FILE *stream, int indent, int fwidth, const void *_key, /*------------------------------------------------------------------------- * Function: H5G__node_free * - * Purpose: Destroy a symbol table node in memory. + * Purpose: Destroy a symbol table node in memory. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 * *------------------------------------------------------------------------- */ @@ -305,29 +300,29 @@ H5G__node_free(H5G_node_t *sym) * Function: H5G_node_create * * Purpose: Creates a new empty symbol table node. This function is - * called by the B-tree insert function for an empty tree. It - * is also called internally to split a symbol node with LT_KEY - * and RT_KEY null pointers. + * called by the B-tree insert function for an empty tree. It + * is also called internally to split a symbol node with LT_KEY + * and RT_KEY null pointers. * - * Return: Success: Non-negative. The address of symbol table - * node is returned through the ADDR_P argument. + * Return: Success: Non-negative. The address of symbol table + * node is returned through the ADDR_P argument. * - * Failure: Negative + * Failure: Negative * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 * *------------------------------------------------------------------------- */ static herr_t H5G_node_create(H5F_t *f, hid_t dxpl_id, H5B_ins_t H5_ATTR_UNUSED op, void *_lt_key, - void H5_ATTR_UNUSED *_udata, void *_rt_key, haddr_t *addr_p/*out*/) + void H5_ATTR_UNUSED *_udata, void *_rt_key, haddr_t *addr_p/*out*/) { - H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key; - H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; - H5G_node_t *sym = NULL; - herr_t ret_value = SUCCEED; /* Return value */ + H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; + H5G_node_t *sym = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -338,15 +333,15 @@ H5G_node_create(H5F_t *f, hid_t dxpl_id, H5B_ins_t H5_ATTR_UNUSED op, void *_lt_ HDassert(H5B_INS_FIRST == op); if(NULL == (sym = H5FL_CALLOC(H5G_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") sym->node_size = H5G_NODE_SIZE(f); if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)sym->node_size))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to allocate file space") + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to allocate file space") if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f))))) - HGOTO_ERROR(H5E_SYM, H5E_CANTALLOC, FAIL, "memory allocation failed") + HGOTO_ERROR(H5E_SYM, H5E_CANTALLOC, FAIL, "memory allocation failed") if(H5AC_insert_entry(f, dxpl_id, H5AC_SNODE, *addr_p, sym, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to cache symbol table leaf node") + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to cache symbol table leaf node") /* * The left and right symbols in an empty tree are both the * empty string stored at offset zero by the H5G functions. This @@ -375,36 +370,36 @@ done: * Function: H5G_node_cmp2 * * Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY). - * The UDATA pointer supplies extra data not contained in the - * keys (in this case, the heap address). + * The UDATA pointer supplies extra data not contained in the + * keys (in this case, the heap address). * - * Return: Success: negative if LT_KEY is less than RT_KEY. + * Return: Success: negative if LT_KEY is less than RT_KEY. * - * positive if LT_KEY is greater than RT_KEY. + * positive if LT_KEY is greater than RT_KEY. * - * zero if LT_KEY and RT_KEY are equal. + * zero if LT_KEY and RT_KEY are equal. * - * Failure: FAIL (same as LT_KEYheap); @@ -416,12 +411,15 @@ H5G_node_cmp2(void *_lt_key, void *_udata, void *_rt_key) HDassert(base); /* Get pointers to string names */ - s1 = base + lt_key->offset; - s2 = base + rt_key->offset; + if((s1 = (const char *)H5HL_offset_into(udata->heap, lt_key->offset)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") + if((s2 = (const char *)H5HL_offset_into(udata->heap, rt_key->offset)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") /* Set return value */ ret_value = HDstrcmp(s1, s2); +done: FUNC_LEAVE_NOAPI(ret_value) } /* H5G_node_cmp2() */ @@ -430,40 +428,40 @@ H5G_node_cmp2(void *_lt_key, void *_udata, void *_rt_key) * Function: H5G_node_cmp3 * * Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY) - * against another key (not necessarily the same type) - * pointed to by UDATA. + * against another key (not necessarily the same type) + * pointed to by UDATA. * - * Return: Success: negative if the UDATA key is less than - * or equal to the LT_KEY + * Return: Success: negative if the UDATA key is less than + * or equal to the LT_KEY * - * positive if the UDATA key is greater - * than the RT_KEY. + * positive if the UDATA key is greater + * than the RT_KEY. * - * zero if the UDATA key falls between - * the LT_KEY (exclusive) and the - * RT_KEY (inclusive). + * zero if the UDATA key falls between + * the LT_KEY (exclusive) and the + * RT_KEY (inclusive). * - * Failure: FAIL (same as UDATA < LT_KEY) + * Failure: FAIL (same as UDATA < LT_KEY) * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static int +static herr_t H5G_node_cmp3(void *_lt_key, void *_udata, void *_rt_key) { - H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata; - H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; - H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; - const char *s; - const char *base; /* Base of heap */ - int ret_value = 0; /* Return value */ + H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata; + H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; + const char *s; + const char *base; /* Base of heap */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT /* Sanity checks */ HDassert(udata && udata->heap); @@ -475,43 +473,46 @@ H5G_node_cmp3(void *_lt_key, void *_udata, void *_rt_key) HDassert(base); /* left side */ - s = base + lt_key->offset; + if((s = (const char *)H5HL_offset_into(udata->heap, lt_key->offset)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") if(HDstrcmp(udata->name, s) <= 0) - ret_value = (-1); + ret_value = (-1); else { /* right side */ - s = base + rt_key->offset; + if((s = (const char *)H5HL_offset_into(udata->heap, rt_key->offset)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") if(HDstrcmp(udata->name, s) > 0) ret_value = 1; } /* end else */ +done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_node_cmp3() */ /*------------------------------------------------------------------------- - * Function: H5G_node_found + * Function: H5G_node_found * - * Purpose: The B-tree search engine has found the symbol table node - * which contains the requested symbol if the symbol exists. - * This function should examine that node for the symbol and - * return information about the symbol through the UDATA - * structure which contains the symbol name on function - * entry. + * Purpose: The B-tree search engine has found the symbol table node + * which contains the requested symbol if the symbol exists. + * This function should examine that node for the symbol and + * return information about the symbol through the UDATA + * structure which contains the symbol name on function + * entry. * - * If the operation flag in UDATA is H5G_OPER_FIND, then - * the entry is copied from the symbol table to the UDATA - * entry field. Otherwise the entry is copied from the - * UDATA entry field to the symbol table. + * If the operation flag in UDATA is H5G_OPER_FIND, then + * the entry is copied from the symbol table to the UDATA + * entry field. Otherwise the entry is copied from the + * UDATA entry field to the symbol table. * - * Return: Success: Non-negative (TRUE/FALSE) if found and data - * returned through the UDATA pointer. + * Return: Success: Non-negative (TRUE/FALSE) if found and data + * returned through the UDATA pointer. * - * Failure: Negative if not found. + * Failure: Negative if not found. * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 * *------------------------------------------------------------------------- */ @@ -519,13 +520,13 @@ static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED *_lt_key, void *_udata) { - H5G_bt_lkp_t *udata = (H5G_bt_lkp_t *)_udata; - H5G_node_t *sn = NULL; - unsigned lt = 0, idx = 0, rt; - int cmp = 1; - const char *s; - const char *base; /* Base of heap */ - htri_t ret_value = TRUE; /* Return value */ + H5G_bt_lkp_t *udata = (H5G_bt_lkp_t *)_udata; + H5G_node_t *sn = NULL; + unsigned lt = 0, idx = 0, rt; + int cmp = 1; + const char *s; + const char *base; /* Base of heap */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -540,7 +541,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED * Load the symbol table node for exclusive access. */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node") /* Get base address of heap */ base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); @@ -551,14 +552,16 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED */ rt = sn->nsyms; while(lt < rt && cmp) { - idx = (lt + rt) / 2; - s = base + sn->entry[idx].name_off; - cmp = HDstrcmp(udata->common.name, s); - - if (cmp < 0) - rt = idx; - else - lt = idx + 1; + idx = (lt + rt) / 2; + + if((s = (const char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table name") + cmp = HDstrcmp(udata->common.name, s); + + if (cmp < 0) + rt = idx; + else + lt = idx + 1; } /* end while */ if(cmp) @@ -570,43 +573,41 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED done: if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node") + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_node_found() */ /*------------------------------------------------------------------------- - * Function: H5G_node_insert + * Function: H5G_node_insert * - * Purpose: The B-tree insertion engine has found the symbol table node - * which should receive the new symbol/address pair. This - * function adds it to that node unless it already existed. + * Purpose: The B-tree insertion engine has found the symbol table node + * which should receive the new symbol/address pair. This + * function adds it to that node unless it already existed. * - * If the node has no room for the symbol then the node is - * split into two nodes. The original node contains the - * low values and the new node contains the high values. - * The new symbol table entry is added to either node as - * appropriate. When a split occurs, this function will - * write the maximum key of the low node to the MID buffer - * and return the address of the new node. + * If the node has no room for the symbol then the node is + * split into two nodes. The original node contains the + * low values and the new node contains the high values. + * The new symbol table entry is added to either node as + * appropriate. When a split occurs, this function will + * write the maximum key of the low node to the MID buffer + * and return the address of the new node. * - * If the new key is larger than RIGHT then update RIGHT - * with the new key. + * If the new key is larger than RIGHT then update RIGHT + * with the new key. * - * Return: Success: An insertion command for the caller, one of - * the H5B_INS_* constants. The address of the - * new node, if any, is returned through the - * NEW_NODE_P argument. NEW_NODE_P might not be - * initialized if the return value is - * H5B_INS_NOOP. + * Return: Success: An insertion command for the caller, one of + * the H5B_INS_* constants. The address of the + * new node, if any, is returned through the + * NEW_NODE_P argument. NEW_NODE_P might not be + * initialized if the return value is H5B_INS_NOOP. * - * Failure: H5B_INS_ERROR, NEW_NODE_P might not be - * initialized. + * Failure: H5B_INS_ERROR, NEW_NODE_P might not be initialized. * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 24 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 24 1997 * *------------------------------------------------------------------------- */ @@ -617,18 +618,18 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node_p) { - H5G_node_key_t *md_key = (H5G_node_key_t *) _md_key; - H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; - H5G_bt_ins_t *udata = (H5G_bt_ins_t *) _udata; - H5G_node_t *sn = NULL, *snrt = NULL; - unsigned sn_flags = H5AC__NO_FLAGS_SET, snrt_flags = H5AC__NO_FLAGS_SET; - const char *s; - const char *base; /* Base of heap */ - unsigned lt = 0, rt; /* Binary search cntrs */ - int cmp = 1, idx = -1; - H5G_node_t *insert_into = NULL; /*node that gets new entry*/ - H5G_entry_t ent; /* Entry to insert in node */ - H5B_ins_t ret_value = H5B_INS_ERROR; + H5G_node_key_t *md_key = (H5G_node_key_t *) _md_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; + H5G_bt_ins_t *udata = (H5G_bt_ins_t *) _udata; + H5G_node_t *sn = NULL, *snrt = NULL; + unsigned sn_flags = H5AC__NO_FLAGS_SET, snrt_flags = H5AC__NO_FLAGS_SET; + const char *s; + const char *base; /* Base of heap */ + unsigned lt = 0, rt; /* Binary search cntrs */ + int cmp = 1, idx = -1; + H5G_node_t *insert_into = NULL; /*node that gets new entry*/ + H5G_entry_t ent; /* Entry to insert in node */ + H5B_ins_t ret_value = H5B_INS_ERROR; FUNC_ENTER_NOAPI_NOINIT @@ -646,7 +647,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, * Load the symbol node. */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") /* Get base address of heap */ base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); @@ -657,85 +658,86 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, */ rt = sn->nsyms; while(lt < rt) { - idx = (int)((lt + rt) / 2); - s = base + sn->entry[idx].name_off; + idx = (int)((lt + rt) / 2); + if((s = (const char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table name") /* Check if symbol is already present */ - if(0 == (cmp = HDstrcmp(udata->common.name, s))) + if(0 == (cmp = HDstrcmp(udata->common.name, s))) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "symbol is already present in symbol table") - if (cmp < 0) - rt = (unsigned)idx; - else - lt = (unsigned)(idx + 1); + if (cmp < 0) + rt = (unsigned)idx; + else + lt = (unsigned)(idx + 1); } /* end while */ idx += cmp > 0 ? 1 : 0; /* Convert link information & name to symbol table entry */ if(H5G__ent_convert(f, dxpl_id, udata->common.heap, udata->common.name, udata->lnk, udata->obj_type, udata->crt_info, &ent) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5B_INS_ERROR, "unable to convert link") + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5B_INS_ERROR, "unable to convert link") /* Determine where to place entry in node */ if(sn->nsyms >= 2 * H5F_SYM_LEAF_K(f)) { - /* - * The node is full. Split it into a left and right - * node and return the address of the new right node (the - * left node is at the same address as the original node). - */ - ret_value = H5B_INS_RIGHT; - - /* The right node */ - if(H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node") - - if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, f, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node") - - HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f), - H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); - snrt->nsyms = H5F_SYM_LEAF_K(f); + /* + * The node is full. Split it into a left and right + * node and return the address of the new right node (the + * left node is at the same address as the original node). + */ + ret_value = H5B_INS_RIGHT; + + /* The right node */ + if(H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node") + + if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, f, H5AC_WRITE))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node") + + HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f), + H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); + snrt->nsyms = H5F_SYM_LEAF_K(f); snrt_flags |= H5AC__DIRTIED_FLAG; - /* The left node */ - HDmemset(sn->entry + H5F_SYM_LEAF_K(f), 0, - H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); - sn->nsyms = H5F_SYM_LEAF_K(f); + /* The left node */ + HDmemset(sn->entry + H5F_SYM_LEAF_K(f), 0, + H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); + sn->nsyms = H5F_SYM_LEAF_K(f); sn_flags |= H5AC__DIRTIED_FLAG; - /* The middle key */ - md_key->offset = sn->entry[sn->nsyms - 1].name_off; + /* The middle key */ + md_key->offset = sn->entry[sn->nsyms - 1].name_off; - /* Where to insert the new entry? */ - if(idx <= (int)H5F_SYM_LEAF_K(f)) { - insert_into = sn; - if(idx == (int)H5F_SYM_LEAF_K(f)) - md_key->offset = ent.name_off; - } /* end if */ + /* Where to insert the new entry? */ + if(idx <= (int)H5F_SYM_LEAF_K(f)) { + insert_into = sn; + if(idx == (int)H5F_SYM_LEAF_K(f)) + md_key->offset = ent.name_off; + } /* end if */ else { - idx -= H5F_SYM_LEAF_K(f); - insert_into = snrt; - if(idx == (int)H5F_SYM_LEAF_K(f)) { - rt_key->offset = ent.name_off; - *rt_key_changed = TRUE; - } /* end if */ - } /* end else */ + idx -= H5F_SYM_LEAF_K(f); + insert_into = snrt; + if(idx == (int)H5F_SYM_LEAF_K(f)) { + rt_key->offset = ent.name_off; + *rt_key_changed = TRUE; + } /* end if */ + } /* end else */ } /* end if */ else { - /* Where to insert the new entry? */ - ret_value = H5B_INS_NOOP; + /* Where to insert the new entry? */ + ret_value = H5B_INS_NOOP; sn_flags |= H5AC__DIRTIED_FLAG; - insert_into = sn; - if(idx == (int)sn->nsyms) { - rt_key->offset = ent.name_off; - *rt_key_changed = TRUE; - } /* end if */ + insert_into = sn; + if(idx == (int)sn->nsyms) { + rt_key->offset = ent.name_off; + *rt_key_changed = TRUE; + } /* end if */ } /* end else */ /* Move entries down to make room for new entry */ HDassert(idx >= 0); HDmemmove(insert_into->entry + idx + 1, insert_into->entry + idx, - (insert_into->nsyms - (unsigned)idx) * sizeof(H5G_entry_t)); + (insert_into->nsyms - (unsigned)idx) * sizeof(H5G_entry_t)); /* Copy new entry into table */ H5G__ent_copy(&(insert_into->entry[idx]), &ent, H5_COPY_SHALLOW); @@ -745,56 +747,56 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, done: if(snrt && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, *new_node_p, snrt, snrt_flags) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_node_insert() */ /*------------------------------------------------------------------------- - * Function: H5G_node_remove + * Function: H5G_node_remove * - * Purpose: The B-tree removal engine has found the symbol table node - * which should contain the name which is being removed. This - * function removes the name from the symbol table and - * decrements the link count on the object to which the name - * points. + * Purpose: The B-tree removal engine has found the symbol table node + * which should contain the name which is being removed. This + * function removes the name from the symbol table and + * decrements the link count on the object to which the name + * points. * - * If the udata->name parameter is set to NULL, then remove - * all entries in this symbol table node. This only occurs - * during the deletion of the entire group, so don't bother - * freeing individual name entries in the local heap, the group's - * symbol table removal code will just free the entire local - * heap eventually. Do reduce the link counts for each object - * however. + * If the udata->name parameter is set to NULL, then remove + * all entries in this symbol table node. This only occurs + * during the deletion of the entire group, so don't bother + * freeing individual name entries in the local heap, the group's + * symbol table removal code will just free the entire local + * heap eventually. Do reduce the link counts for each object + * however. * - * Return: Success: If all names are removed from the symbol - * table node then H5B_INS_REMOVE is returned; - * otherwise H5B_INS_NOOP is returned. + * Return: Success: If all names are removed from the symbol + * table node then H5B_INS_REMOVE is returned; + * otherwise H5B_INS_NOOP is returned. * - * Failure: H5B_INS_ERROR + * Failure: H5B_INS_ERROR * - * Programmer: Robb Matzke + * Programmer: Robb Matzke * Thursday, September 24, 1998 * *------------------------------------------------------------------------- */ static H5B_ins_t H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, - hbool_t H5_ATTR_UNUSED *lt_key_changed/*out*/, - void *_udata/*in,out*/, void *_rt_key/*in,out*/, - hbool_t *rt_key_changed/*out*/) + hbool_t H5_ATTR_UNUSED *lt_key_changed/*out*/, + void *_udata/*in,out*/, void *_rt_key/*in,out*/, + hbool_t *rt_key_changed/*out*/) { - H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key; - H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; - H5G_bt_rm_t *udata = (H5G_bt_rm_t *)_udata; - H5G_node_t *sn = NULL; - unsigned sn_flags = H5AC__NO_FLAGS_SET; - unsigned lt = 0, rt, idx = 0; - int cmp = 1; - H5B_ins_t ret_value = H5B_INS_ERROR; + H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; + H5G_bt_rm_t *udata = (H5G_bt_rm_t *)_udata; + H5G_node_t *sn = NULL; + unsigned sn_flags = H5AC__NO_FLAGS_SET; + unsigned lt = 0, rt, idx = 0; + int cmp = 1; + H5B_ins_t ret_value = H5B_INS_ERROR; FUNC_ENTER_NOAPI_NOINIT @@ -807,7 +809,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, /* Load the symbol table */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") /* "Normal" removal of a single entry from the symbol table node */ if(udata->common.name != NULL) { @@ -824,7 +826,8 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, const char *s; /* Pointer to string in local heap */ idx = (lt + rt) / 2; - s = base + sn->entry[idx].name_off; + if((s = H5HL_offset_into(udata->common.heap, sn->entry[idx].name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table name") cmp = HDstrcmp(udata->common.name, s); if(cmp < 0) rt = idx; @@ -846,7 +849,8 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, lnk.cset = H5T_CSET_ASCII; if(sn->entry[idx].type == H5G_CACHED_SLINK) { lnk.type = H5L_TYPE_SOFT; - lnk.u.soft.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].cache.slink.lval_offset); + if(NULL == (lnk.u.soft.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].cache.slink.lval_offset))) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to get link name") } /* end if */ else { lnk.type = H5L_TYPE_HARD; @@ -960,22 +964,22 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, done: if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTUNPROTECT, H5B_INS_ERROR, "unable to release symbol table node") + HDONE_ERROR(H5E_SYM, H5E_CANTUNPROTECT, H5B_INS_ERROR, "unable to release symbol table node") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_node_remove() */ /*------------------------------------------------------------------------- - * Function: H5G__node_iterate + * Function: H5G__node_iterate * - * Purpose: This function gets called during a group iterate operation. + * Purpose: This function gets called during a group iterate operation. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 24 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 24 1997 * *------------------------------------------------------------------------- */ @@ -983,11 +987,11 @@ int H5G__node_iterate(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, const void H5_ATTR_UNUSED *_rt_key, void *_udata) { - H5G_bt_it_it_t *udata = (H5G_bt_it_it_t *)_udata; - H5G_node_t *sn = NULL; - H5G_entry_t *ents; /* Pointer to entries in this node */ - unsigned u; /* Local index variable */ - int ret_value = H5_ITER_CONT; + H5G_bt_it_it_t *udata = (H5G_bt_it_it_t *)_udata; + H5G_node_t *sn = NULL; + H5G_entry_t *ents; /* Pointer to entries in this node */ + unsigned u; /* Local index variable */ + int ret_value = H5_ITER_CONT; FUNC_ENTER_PACKAGE @@ -1000,7 +1004,7 @@ H5G__node_iterate(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, h /* Protect the symbol table node & local heap while we iterate over entries */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") /* * Iterate over the symbol table node entries. @@ -1013,7 +1017,8 @@ H5G__node_iterate(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, h const char *name; /* Pointer to link name in heap */ /* Get the pointer to the name of the link in the heap */ - name = (const char *)H5HL_offset_into(udata->heap, ents[u].name_off); + if((name = (const char *)H5HL_offset_into(udata->heap, ents[u].name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get symbol table node name") HDassert(name); /* Convert the entry to a link */ @@ -1043,15 +1048,14 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__node_iterate() */ - /*------------------------------------------------------------------------- - * Function: H5G__node_sumup + * Function: H5G__node_sumup * - * Purpose: This function gets called during a group iterate operation + * Purpose: This function gets called during a group iterate operation * to return total number of members in the group. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Nov 20, 2002 @@ -1060,11 +1064,11 @@ done: */ int H5G__node_sumup(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, - const void H5_ATTR_UNUSED *_rt_key, void *_udata) + const void H5_ATTR_UNUSED *_rt_key, void *_udata) { hsize_t *num_objs = (hsize_t *)_udata; - H5G_node_t *sn = NULL; - int ret_value = H5_ITER_CONT; + H5G_node_t *sn = NULL; + int ret_value = H5_ITER_CONT; FUNC_ENTER_PACKAGE @@ -1077,7 +1081,7 @@ H5G__node_sumup(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, had /* Find the object node and add the number of symbol entries. */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") *num_objs += sn->nsyms; @@ -1090,12 +1094,12 @@ done: /*------------------------------------------------------------------------- - * Function: H5G__node_by_idx + * Function: H5G__node_by_idx * - * Purpose: This function gets called during a group iterate operation + * Purpose: This function gets called during a group iterate operation * to return object name by giving idx. * - * Return: 0 if object isn't found in this node; 1 if object is found; + * Return: 0 if object isn't found in this node; 1 if object is found; * Negative on failure * * Programmer: Raymond Lu @@ -1105,11 +1109,11 @@ done: */ int H5G__node_by_idx(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, - const void H5_ATTR_UNUSED *_rt_key, void *_udata) + const void H5_ATTR_UNUSED *_rt_key, void *_udata) { - H5G_bt_it_idx_common_t *udata = (H5G_bt_it_idx_common_t *)_udata; - H5G_node_t *sn = NULL; - int ret_value = H5_ITER_CONT; + H5G_bt_it_idx_common_t *udata = (H5G_bt_it_idx_common_t *)_udata; + H5G_node_t *sn = NULL; + int ret_value = H5_ITER_CONT; FUNC_ENTER_PACKAGE @@ -1122,7 +1126,7 @@ H5G__node_by_idx(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, ha /* Get a pointer to the symbol table node */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node"); + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node"); /* Find the node, locate the object symbol table entry and retrieve the name */ if(udata->idx >= udata->num_objs && udata->idx < (udata->num_objs + sn->nsyms)) { @@ -1151,12 +1155,12 @@ done: /*------------------------------------------------------------------------- - * Function: H5G__node_init + * Function: H5G__node_init * - * Purpose: This function gets called during a file opening to initialize + * Purpose: This function gets called during a file opening to initialize * global information about group B-tree nodes for file. * - * Return: Non-negative on success + * Return: Non-negative on success * Negative on failure * * Programmer: Quincey Koziol @@ -1167,9 +1171,9 @@ done: herr_t H5G__node_init(H5F_t *f) { - H5B_shared_t *shared; /* Shared B-tree node info */ - size_t sizeof_rkey; /* Size of raw (disk) key */ - herr_t ret_value = SUCCEED; /* Return value */ + H5B_shared_t *shared; /* Shared B-tree node info */ + size_t sizeof_rkey; /* Size of raw (disk) key */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -1181,14 +1185,14 @@ H5G__node_init(H5F_t *f) /* Allocate & initialize global info for the shared structure */ if(NULL == (shared = H5B_shared_new(f, H5B_SNODE, sizeof_rkey))) - HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info") + HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info") /* Set up the "local" information for this file's groups */ - /* */ + /* */ /* Make shared B-tree info reference counted */ if(H5F_SET_GRP_BTREE_SHARED(f, H5RC_create(shared, H5B_shared_free)) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1196,12 +1200,12 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_node_close + * Function: H5G_node_close * - * Purpose: This function gets called during a file close to shutdown + * Purpose: This function gets called during a file close to shutdown * global information about group B-tree nodes for file. * - * Return: Non-negative on success + * Return: Non-negative on success * Negative on failure * * Programmer: Quincey Koziol @@ -1227,12 +1231,12 @@ H5G_node_close(const H5F_t *f) /*------------------------------------------------------------------------- - * Function: H5G__node_copy + * Function: H5G__node_copy * - * Purpose: This function gets called during a group iterate operation + * Purpose: This function gets called during a group iterate operation * to copy objects of this node into a new location. * - * Return: 0(zero) on success/Negative on failure + * Return: 0(zero) on success/Negative on failure * * Programmer: Peter Cao * Sept 10, 2005 @@ -1241,7 +1245,7 @@ H5G_node_close(const H5F_t *f) */ int H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, - const void H5_ATTR_UNUSED *_rt_key, void *_udata) + const void H5_ATTR_UNUSED *_rt_key, void *_udata) { H5G_bt_it_cpy_t *udata = (H5G_bt_it_cpy_t *)_udata; const H5O_loc_t *src_oloc = udata->src_oloc; @@ -1260,7 +1264,7 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd /* load the symbol table into memory from the source file */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") /* get the base address of the heap */ if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->src_heap_addr, H5AC_READ))) @@ -1292,7 +1296,8 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Get pointer to link value in local heap */ - link_name = (char *)H5HL_offset_into(heap, tmp_src_ent.cache.slink.lval_offset); + if((link_name = (char *)H5HL_offset_into(heap, tmp_src_ent.cache.slink.lval_offset)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get link name") /* Check if the object pointed by the soft link exists in the source file */ if(H5G_loc_info(&grp_loc, link_name, FALSE, &oinfo, H5P_DEFAULT, dxpl_id) >= 0) { @@ -1342,7 +1347,8 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd /* Construct link information for eventual insertion */ lnk.type = H5L_TYPE_SOFT; - lnk.u.soft.name = (char *)H5HL_offset_into(heap, src_ent->cache.slink.lval_offset); + if((lnk.u.soft.name = (char *)H5HL_offset_into(heap, src_ent->cache.slink.lval_offset)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get link name") } /* else if */ else HDassert(0 && "Unknown entry type"); @@ -1354,8 +1360,9 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd /* lnk.name = name; */ /* This will be set in callback */ /* Determine name of source object */ - name = (const char *)H5HL_offset_into(heap, src_ent->name_off); - HDassert(name); + if((name = (const char *)H5HL_offset_into(heap, src_ent->name_off)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get source object name") + HDassert(name); /* Insert the new object in the destination file's group */ /* (Don't increment the link count - that's already done above for hard links) */ @@ -1377,15 +1384,15 @@ done: /*------------------------------------------------------------------------- - * Function: H5G__node_build_table + * Function: H5G__node_build_table * - * Purpose: B-link tree callback for building table of links + * Purpose: B-link tree callback for building table of links * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Nov 19 2006 + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 19 2006 * *------------------------------------------------------------------------- */ @@ -1393,10 +1400,10 @@ int H5G__node_build_table(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, const void H5_ATTR_UNUSED *_rt_key, void *_udata) { - H5G_bt_it_bt_t *udata = (H5G_bt_it_bt_t *)_udata; - H5G_node_t *sn = NULL; /* Symbol table node */ - unsigned u; /* Local index variable */ - int ret_value = H5_ITER_CONT; + H5G_bt_it_bt_t *udata = (H5G_bt_it_bt_t *)_udata; + H5G_node_t *sn = NULL; /* Symbol table node */ + unsigned u; /* Local index variable */ + int ret_value = H5_ITER_CONT; FUNC_ENTER_PACKAGE @@ -1412,7 +1419,7 @@ H5G__node_build_table(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_ke * because we're about to call an application function. */ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node") /* Check if the link table needs to be extended */ if((udata->ltable->nlinks + sn->nsyms) >= udata->alloc_nlinks) { @@ -1431,7 +1438,8 @@ H5G__node_build_table(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_ke size_t linkno; /* Link allocated */ /* Get pointer to link's name in the heap */ - name = (const char *)H5HL_offset_into(udata->heap, sn->entry[u].name_off); + if((name = (const char *)H5HL_offset_into(udata->heap, sn->entry[u].name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get symbol table link name") HDassert(name); /* Determine the link to operate on in the table */ @@ -1465,8 +1473,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G__node_iterate_size(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, const void H5_ATTR_UNUSED *_lt_key, haddr_t H5_ATTR_UNUSED addr, - const void H5_ATTR_UNUSED *_rt_key, void *_udata) +H5G__node_iterate_size(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, const void H5_ATTR_UNUSED *_lt_key, + haddr_t H5_ATTR_UNUSED addr, const void H5_ATTR_UNUSED *_rt_key, void *_udata) { hsize_t *stab_size = (hsize_t *)_udata; /* User data */ @@ -1483,16 +1491,16 @@ H5G__node_iterate_size(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, const void H5_ATT /*------------------------------------------------------------------------- - * Function: H5G_node_debug + * Function: H5G_node_debug * - * Purpose: Prints debugging information about a symbol table node - * or a B-tree node for a symbol table B-tree. + * Purpose: Prints debugging information about a symbol table node + * or a B-tree node for a symbol table B-tree. * - * Return: 0(zero) on success/Negative on failure + * Return: 0(zero) on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 4 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 4 1997 * *------------------------------------------------------------------------- */ @@ -1500,10 +1508,10 @@ herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth, haddr_t heap_addr) { - H5G_node_t *sn = NULL; - H5HL_t *heap = NULL; - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5G_node_t *sn = NULL; + H5HL_t *heap = NULL; + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1530,8 +1538,8 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, H5E_clear_stack(NULL); /* discard that error */ udata.heap = heap; - if(H5B_debug(f, dxpl_id, addr, stream, indent, fwidth, H5B_SNODE, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to debug B-tree node"); + if(H5B_debug(f, dxpl_id, addr, stream, indent, fwidth, H5B_SNODE, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to debug B-tree node"); } /* end if */ else { fprintf(stream, "%*sSymbol Table Node...\n", indent, ""); @@ -1564,7 +1572,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, done: if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node") + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node") if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") diff --git a/src/H5Gstab.c b/src/H5Gstab.c index f9a8884..01dbdbc 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -707,11 +707,12 @@ done: static herr_t H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata) { - H5G_bt_it_gnbi_t *udata = (H5G_bt_it_gnbi_t *)_udata; + H5G_bt_it_gnbi_t *udata = (H5G_bt_it_gnbi_t *)_udata; size_t name_off; /* Offset of name in heap */ const char *name; /* Pointer to name string in heap */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(ent); @@ -719,12 +720,16 @@ H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata) /* Get name offset in heap */ name_off = ent->name_off; - name = (const char *)H5HL_offset_into(udata->heap, name_off); + + if((name = (const char *)H5HL_offset_into(udata->heap, name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table link name") + HDassert(name); udata->name = H5MM_strdup(name); HDassert(udata->name); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_get_name_by_idx_cb */ @@ -941,7 +946,8 @@ H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata) HDassert(udata && udata->heap); /* Get a pointer to the link name */ - name = (const char *)H5HL_offset_into(udata->heap, ent->name_off); + if((name = (const char *)H5HL_offset_into(udata->heap, ent->name_off)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table link name") HDassert(name); /* Convert the entry to a link */ diff --git a/src/H5HL.c b/src/H5HL.c index b731647..01ace76 100644 --- a/src/H5HL.c +++ b/src/H5HL.c @@ -533,17 +533,18 @@ done: void * H5HL_offset_into(const H5HL_t *heap, size_t offset) { - /* - * We need to have called some other function before this to get a - * valid heap pointer. So, this can remain "FUNC_ENTER_NOAPI_NOINIT" - */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + void *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) /* Sanity check */ HDassert(heap); - HDassert(offset < heap->dblk_size); + if(offset >= heap->dblk_size) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to offset into local heap data block") + ret_value = heap->dblk_image + offset; - FUNC_LEAVE_NOAPI(heap->dblk_image + offset) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_offset_into() */ diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 1de3059..c4b1d96 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -67,17 +67,17 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{ /*------------------------------------------------------------------------- - * Function: H5O_efl_decode + * Function: H5O_efl_decode * * Purpose: Decode an external file list message and return a pointer to - * the message (and some other data). + * the message (and some other data). * - * Return: Success: Ptr to a new message struct. + * Return: Success: Ptr to a new message struct. * - * Failure: NULL + * Failure: NULL * * Programmer: Robb Matzke - * Tuesday, November 25, 1997 + * Tuesday, November 25, 1997 * * Modification: * Raymond Lu @@ -90,12 +90,12 @@ static void * H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p) { - H5O_efl_t *mesg = NULL; - int version; - const char *s = NULL; - H5HL_t *heap; - size_t u; /* Local index variable */ - void *ret_value; /* Return value */ + H5O_efl_t *mesg = NULL; + int version; + const char *s = NULL; + H5HL_t *heap; + size_t u; /* Local index variable */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -104,12 +104,12 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, HDassert(p); if(NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Version */ version = *p++; if(version != H5O_EFL_VERSION) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message") /* Reserved */ p += 3; @@ -141,24 +141,25 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, /* Decode the file list */ mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t)); if(NULL == mesg->slot) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value") for(u = 0; u < mesg->nused; u++) { - /* Name */ - H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset); + /* Name */ + H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset); - s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset); - HDassert(s && *s); - mesg->slot[u].name = H5MM_xstrdup (s); + if((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "unable to get external file name") + HDassert(s && *s); + mesg->slot[u].name = H5MM_xstrdup (s); HDassert(mesg->slot[u].name); - /* File offset */ - H5F_DECODE_LENGTH (f, p, mesg->slot[u].offset); + /* File offset */ + H5F_DECODE_LENGTH (f, p, mesg->slot[u].offset); - /* Size */ - H5F_DECODE_LENGTH (f, p, mesg->slot[u].size); + /* Size */ + H5F_DECODE_LENGTH (f, p, mesg->slot[u].size); } /* end for */ if(H5HL_unprotect(heap) < 0) diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake index 154fed9..8e2c48b 100644 --- a/test/CMakeTests.cmake +++ b/test/CMakeTests.cmake @@ -103,6 +103,7 @@ endif () # -------------------------------------------------------------------- set (HDF5_REFERENCE_TEST_FILES bad_compound.h5 + bad_offset.h5 be_data.h5 be_extlink1.h5 be_extlink2.h5 @@ -1016,6 +1017,7 @@ if (HDF5_BUILD_GENERATORS) # generator executables set (H5_GENERATORS + gen_bad_offset gen_bad_ohdr gen_bogus gen_cross diff --git a/test/Makefile.am b/test/Makefile.am index 7fbccdd..7c55e5b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -67,7 +67,7 @@ endif BUILD_ALL_PROGS=gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_idx \ gen_new_array gen_new_fill gen_new_group gen_new_mtime gen_new_super \ gen_noencoder gen_nullspace gen_udlinks space_overflow gen_sizes_lheap \ - gen_file_image + gen_file_image gen_bad_offset if BUILD_ALL_CONDITIONAL noinst_PROGRAMS=$(BUILD_ALL_PROGS) diff --git a/test/bad_offset.h5 b/test/bad_offset.h5 new file mode 100644 index 0000000..6500ffe Binary files /dev/null and b/test/bad_offset.h5 differ diff --git a/test/gen_bad_offset.c b/test/gen_bad_offset.c new file mode 100644 index 0000000..2be4af1 --- /dev/null +++ b/test/gen_bad_offset.c @@ -0,0 +1,112 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * 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://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Generate an HDF5 file for testing H5FFV-10216 + */ +#include "h5test.h" + +#define TESTFILE "bad_offset.h5" +#define GRP1 "group1" +#define GRP2 "group2" +#define DSET "dsetA" +#define SOFT1 "soft_one" +#define SOFT2 "soft_two" + + + +/*------------------------------------------------------------------------- + * Function: main + * Generate an HDF5 file with groups, datasets and symbolic links. + * + * After this file is generated, write bad offset values to + * the heap at 3 locations in the file: + * (A) Open the file: + * fd = HDopen(TESTFILE, O_RDWR, 0663); + * (B) Position the file at: + * (1) HDlseek(fd, (HDoff_t)880, SEEK_SET); + * "/group1/group2": replace heap offset "8" by bad offset + * (2) HDlseek(fd, (HDoff_t)1512, SEEK_SET); + * "/dsetA": replace name offset into private heap "72" by bad offset + * (3) HDlseek(fd, (HDoff_t)1616, SEEK_SET); + * /soft_one: replace link value offset in the scratch pad "32" by bad offset + * (C) Write the bad offset value to the file: + * write(fd, &val, sizeof(val)); + * + * Note: if the groups/datasets/symbolic links are changed in the file, + * the above locations need to be adjusted accordingly. + * + * Return: EXIT_SUCCESS/EXIT_FAILURE + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + hid_t fid = -1, gid1 = -1, gid2 = -1; /* File and group IDs */ + hid_t did = -1, sid = -1; /* Dataset and dataspace IDs */ + + /* Create the test file */ + if((fid = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Create two groups */ + if((gid1 = H5Gcreate2(fid, GRP1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + if((gid2 = H5Gcreate2(gid1, GRP2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Close the groups */ + if(H5Gclose(gid1) < 0) + FAIL_STACK_ERROR + if(H5Gclose(gid2) < 0) + FAIL_STACK_ERROR + + /* Create soft links to the groups */ + if(H5Lcreate_soft("/group1", fid, SOFT1, H5P_DEFAULT, H5P_DEFAULT) < 0) + FAIL_STACK_ERROR + if(H5Lcreate_soft("/group1/group2", fid, SOFT2, H5P_DEFAULT, H5P_DEFAULT) < 0) + FAIL_STACK_ERROR + + /* Create a dataset */ + if((sid = H5Screate(H5S_SCALAR)) < 0) + FAIL_STACK_ERROR + if((did = H5Dcreate2(fid, DSET, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Close the dataset */ + if(H5Dclose(did) < 0) + FAIL_STACK_ERROR + + /* Close the dataspace */ + if(H5Sclose(sid) < 0) + FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + return EXIT_SUCCESS; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid1); + H5Gclose(gid2); + H5Dclose(did); + H5Sclose(sid); + H5Fclose(fid); + } H5E_END_TRY; + + return EXIT_FAILURE; +} /* end main() */ + diff --git a/test/tmisc.c b/test/tmisc.c index 9766816..980c9ea 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -323,6 +323,11 @@ unsigned m13_rdata[MISC13_DIM1][MISC13_DIM2]; /* Data read from dataset #define MISC31_PROPNAME "misc31_prop" #define MISC31_DTYPENAME "dtype" +/* Definitions for misc. test #33 */ +/* Note that this test file is generated by "gen_bad_offset.c" */ +/* and bad offset values are written to that file for testing */ +#define MISC33_FILE "bad_offset.h5" + /**************************************************************** ** ** test_misc1(): test unlinking a dataset from a group and immediately @@ -5423,6 +5428,55 @@ test_misc32(void) } /* end test_misc32() */ +/**************************************************************** +** +** test_misc33(): Test for H5FFV-10216 +** --verify that H5HL_offset_into() returns error if the +** input parameter "offset" exceeds heap data block size. +** --case (1), (2), (3) are scenarios that will traverse to the +** the 3 locations in the file having bad offset values to +** the heap. (See description in gen_bad_offset.c) +** +****************************************************************/ +static void +test_misc33(void) +{ + hid_t fid = -1; /* File ID */ + const char *testfile = H5_get_srcdir_filename(MISC33_FILE); /* Corrected test file name */ + H5O_info_t oinfo; /* Structure for object metadata information */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing that bad offset into the heap returns error")); + + /* Open the test file */ + fid = H5Fopen(testfile, H5F_ACC_RDWR, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fopen"); + + /* Case (1) */ + H5E_BEGIN_TRY { + ret = H5Oget_info_by_name(fid, "/soft_two", &oinfo, H5P_DEFAULT); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Oget_info_by_name"); + + /* Case (2) */ + H5E_BEGIN_TRY { + ret = H5Oget_info_by_name(fid, "/dsetA", &oinfo, H5P_DEFAULT); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Oget_info_by_name"); + + /* Case (3) */ + H5E_BEGIN_TRY { + ret = H5Oget_info_by_name(fid, "/soft_one", &oinfo, H5P_DEFAULT); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Oget_info_by_name"); + + /* Close the file */ + ret = H5Fclose(fid); + CHECK(fid, FAIL, "H5Fclose"); + +} /* end test_misc33() */ + /**************************************************************** ** @@ -5471,6 +5525,7 @@ test_misc(void) test_misc30(); /* Exercise local heap loading bug where free lists were getting dropped */ test_misc31(); /* Test Reentering library through deprecated routines after H5close() */ test_misc32(); /* Test filter memory allocation functions */ + test_misc33(); /* ??? */ } /* test_misc() */ -- cgit v0.12 From 38194b496d9a868de21c6bcc8bda3bf30690712e Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Wed, 23 Aug 2017 16:23:09 -0500 Subject: Modifications based on comments from pull request review (1) Remove unnecessary asserts (2) Add code to insert bad offset values to the test file in gen_bad_offset.c --- src/H5Glink.c | 21 ++++++++++++++------- src/H5Gnode.c | 43 ++++++++----------------------------------- src/H5Gstab.c | 6 ++---- src/H5Oefl.c | 3 ++- test/bad_offset.h5 | Bin 3312 -> 3312 bytes test/gen_bad_offset.c | 41 ++++++++++++++++++++++++++++++++++++++--- test/tmisc.c | 2 +- 7 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/H5Glink.c b/src/H5Glink.c index fe49458..255add0 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -224,6 +224,7 @@ herr_t H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, const H5G_entry_t *ent, const char *name) { + hbool_t dup_soft = FALSE; /* xstrdup the symbolic link name or not */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -238,19 +239,21 @@ H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, lnk->cset = H5F_DEFAULT_CSET; lnk->corder = 0; lnk->corder_valid = FALSE; /* Creation order not valid for this link */ - lnk->name = H5MM_xstrdup(name); - HDassert(lnk->name); + if((lnk->name = H5MM_xstrdup(name)) == NULL) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to duplicate link name") /* Object is a symbolic or hard link */ if(ent->type == H5G_CACHED_SLINK) { const char *s; /* Pointer to link value */ if((s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset)) == NULL) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link name") - HDassert(s); + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get symbolic link name") /* Copy the link value */ - lnk->u.soft.name = H5MM_xstrdup(s); + if((lnk->u.soft.name = H5MM_xstrdup(s)) == NULL) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to duplicate symbolic link name") + + dup_soft = TRUE; /* Set link type */ lnk->type = H5L_TYPE_SOFT; @@ -264,8 +267,12 @@ H5G__ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, } /* end else */ done: - if(ret_value < 0 && lnk->name) - H5MM_xfree(lnk->name); + if(ret_value < 0) { + if(lnk->name) + H5MM_xfree(lnk->name); + if(ent->type == H5G_CACHED_SLINK && dup_soft) + H5MM_xfree(lnk->u.soft.name); + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__ent_to_link() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 7de9ec9..2c4b840 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -35,7 +35,7 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functionsi */ +#include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ @@ -396,7 +396,6 @@ H5G_node_cmp2(void *_lt_key, void *_udata, void *_rt_key) H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; const char *s1, *s2; - const char *base; /* Base of heap */ int ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -406,10 +405,6 @@ H5G_node_cmp2(void *_lt_key, void *_udata, void *_rt_key) HDassert(lt_key); HDassert(rt_key); - /* Get base address of heap */ - base = (const char *)H5HL_offset_into(udata->heap, (size_t)0); - HDassert(base); - /* Get pointers to string names */ if((s1 = (const char *)H5HL_offset_into(udata->heap, lt_key->offset)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") @@ -458,7 +453,6 @@ H5G_node_cmp3(void *_lt_key, void *_udata, void *_rt_key) H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; const char *s; - const char *base; /* Base of heap */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -468,10 +462,6 @@ H5G_node_cmp3(void *_lt_key, void *_udata, void *_rt_key) HDassert(lt_key); HDassert(rt_key); - /* Get base address of heap */ - base = (const char *)H5HL_offset_into(udata->heap, (size_t)0); - HDassert(base); - /* left side */ if((s = (const char *)H5HL_offset_into(udata->heap, lt_key->offset)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get key name") @@ -525,7 +515,6 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED unsigned lt = 0, idx = 0, rt; int cmp = 1; const char *s; - const char *base; /* Base of heap */ htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -543,10 +532,6 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node") - /* Get base address of heap */ - base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); - HDassert(base); - /* * Binary search. */ @@ -624,7 +609,6 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5G_node_t *sn = NULL, *snrt = NULL; unsigned sn_flags = H5AC__NO_FLAGS_SET, snrt_flags = H5AC__NO_FLAGS_SET; const char *s; - const char *base; /* Base of heap */ unsigned lt = 0, rt; /* Binary search cntrs */ int cmp = 1, idx = -1; H5G_node_t *insert_into = NULL; /*node that gets new entry*/ @@ -649,10 +633,6 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") - /* Get base address of heap */ - base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); - HDassert(base); - /* * Where does the new symbol get inserted? We use a binary search. */ @@ -815,10 +795,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, if(udata->common.name != NULL) { H5O_link_t lnk; /* Constructed link for replacement */ size_t link_name_len; /* Length of string in local heap */ - const char *base; /* Base of heap */ - - /* Get base address of heap */ - base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); /* Find the name with a binary search */ rt = sn->nsyms; @@ -1019,7 +995,6 @@ H5G__node_iterate(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, h /* Get the pointer to the name of the link in the heap */ if((name = (const char *)H5HL_offset_into(udata->heap, ents[u].name_off)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get symbol table node name") - HDassert(name); /* Convert the entry to a link */ if(H5G__ent_to_link(&lnk, udata->heap, &ents[u], name) < 0) @@ -1362,7 +1337,6 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd /* Determine name of source object */ if((name = (const char *)H5HL_offset_into(heap, src_ent->name_off)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get source object name") - HDassert(name); /* Insert the new object in the destination file's group */ /* (Don't increment the link count - that's already done above for hard links) */ @@ -1440,7 +1414,6 @@ H5G__node_build_table(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_ke /* Get pointer to link's name in the heap */ if((name = (const char *)H5HL_offset_into(udata->heap, sn->entry[u].name_off)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get symbol table link name") - HDassert(name); /* Determine the link to operate on in the table */ linkno = udata->ltable->nlinks++; @@ -1542,29 +1515,29 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to debug B-tree node"); } /* end if */ else { - fprintf(stream, "%*sSymbol Table Node...\n", indent, ""); - fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + HDfprintf(stream, "%*sSymbol Table Node...\n", indent, ""); + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Dirty:", sn->cache_info.is_dirty ? "Yes" : "No"); - fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Size of Node (in bytes):", (unsigned)sn->node_size); - fprintf(stream, "%*s%-*s %u of %u\n", indent, "", fwidth, + HDfprintf(stream, "%*s%-*s %u of %u\n", indent, "", fwidth, "Number of Symbols:", sn->nsyms, (unsigned)(2 * H5F_SYM_LEAF_K(f))); indent += 3; fwidth = MAX(0, fwidth - 3); for(u = 0; u < sn->nsyms; u++) { - fprintf(stream, "%*sSymbol %u:\n", indent - 3, "", u); + HDfprintf(stream, "%*sSymbol %u:\n", indent - 3, "", u); if(heap) { const char *s = (const char *)H5HL_offset_into(heap, sn->entry[u].name_off); if(s) - fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s); + HDfprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s); } /* end if */ else - fprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Warning: Invalid heap address given, name not displayed!"); + HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Warning: Invalid heap address given, name not displayed!"); H5G__ent_debug(sn->entry + u, stream, indent, fwidth, heap); } /* end for */ diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 01dbdbc..0eb7b0b 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -724,9 +724,8 @@ H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata) if((name = (const char *)H5HL_offset_into(udata->heap, name_off)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table link name") - HDassert(name); - udata->name = H5MM_strdup(name); - HDassert(udata->name); + if((udata->name = H5MM_strdup(name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to duplicate symbol table link name") done: FUNC_LEAVE_NOAPI(ret_value) @@ -948,7 +947,6 @@ H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata) /* Get a pointer to the link name */ if((name = (const char *)H5HL_offset_into(udata->heap, ent->name_off)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table link name") - HDassert(name); /* Convert the entry to a link */ if(H5G__ent_to_link(udata->lnk, udata->heap, ent, name) < 0) diff --git a/src/H5Oefl.c b/src/H5Oefl.c index c4b1d96..26ac63f 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -151,7 +151,8 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, if((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "unable to get external file name") - HDassert(s && *s); + if(*s == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "invalid external file name") mesg->slot[u].name = H5MM_xstrdup (s); HDassert(mesg->slot[u].name); diff --git a/test/bad_offset.h5 b/test/bad_offset.h5 index 6500ffe..231dca2 100644 Binary files a/test/bad_offset.h5 and b/test/bad_offset.h5 differ diff --git a/test/gen_bad_offset.c b/test/gen_bad_offset.c index 2be4af1..82e94cd 100644 --- a/test/gen_bad_offset.c +++ b/test/gen_bad_offset.c @@ -27,9 +27,9 @@ /*------------------------------------------------------------------------- * Function: main - * Generate an HDF5 file with groups, datasets and symbolic links. * - * After this file is generated, write bad offset values to + * Generate an HDF5 file with groups, datasets and symbolic links. + * After the file is generated, write bad offset values to * the heap at 3 locations in the file: * (A) Open the file: * fd = HDopen(TESTFILE, O_RDWR, 0663); @@ -40,7 +40,7 @@ * "/dsetA": replace name offset into private heap "72" by bad offset * (3) HDlseek(fd, (HDoff_t)1616, SEEK_SET); * /soft_one: replace link value offset in the scratch pad "32" by bad offset - * (C) Write the bad offset value to the file: + * (C) Write the bad offset value to the file for (1), (2) and (3): * write(fd, &val, sizeof(val)); * * Note: if the groups/datasets/symbolic links are changed in the file, @@ -55,6 +55,8 @@ main(void) { hid_t fid = -1, gid1 = -1, gid2 = -1; /* File and group IDs */ hid_t did = -1, sid = -1; /* Dataset and dataspace IDs */ + int fd = -1; /* File descriptor */ + int64_t val = 999; /* Bad offset value */ /* Create the test file */ if((fid = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) @@ -96,6 +98,39 @@ main(void) if(H5Fclose(fid) < 0) FAIL_STACK_ERROR + /* + * Write bad offset values at 3 locations in the file + */ + + /* Open the file */ + if((fd = HDopen(TESTFILE, O_RDWR, 0663)) < 0) + FAIL_STACK_ERROR + + /* Position the file for /group1/group2: replace heap offset "8" by bad offset */ + if(HDlseek(fd, (HDoff_t)880, SEEK_SET) < 0) + FAIL_STACK_ERROR + /* Write the bad offset value to the file */ + if(HDwrite(fd, &val, sizeof(val)) < 0) + FAIL_STACK_ERROR + + /* Position the file for /dsetA: replace name offset into private heap "72" by bad offset */ + if(HDlseek(fd, (HDoff_t)1512, SEEK_SET) < 0) + FAIL_STACK_ERROR + /* Write the bad offset value to the file */ + if(HDwrite(fd, &val, sizeof(val)) < 0) + FAIL_STACK_ERROR + + /* Position the file for /soft_one: replace link value offset in the scratch pad "32" by bad offset */ + if(HDlseek(fd, (HDoff_t)1616, SEEK_SET) < 0) + FAIL_STACK_ERROR + /* Write the bad offset value to the file */ + if(HDwrite(fd, &val, sizeof(val)) < 0) + FAIL_STACK_ERROR + + /* Close the file */ + if(HDclose(fd) < 0) + FAIL_STACK_ERROR + return EXIT_SUCCESS; error: diff --git a/test/tmisc.c b/test/tmisc.c index 980c9ea..aae1a99 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -5525,7 +5525,7 @@ test_misc(void) test_misc30(); /* Exercise local heap loading bug where free lists were getting dropped */ test_misc31(); /* Test Reentering library through deprecated routines after H5close() */ test_misc32(); /* Test filter memory allocation functions */ - test_misc33(); /* ??? */ + test_misc33(); /* Test to verify that H5HL_offset_into() returns error if offset exceeds heap block */ } /* test_misc() */ -- cgit v0.12 From 00c572cd6a75406dc0f45cbadf775015e6e6f105 Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Thu, 24 Aug 2017 11:42:35 -0500 Subject: Fix for daily test failure Fix for the compilation error from the PGI compiler. --- src/H5Oefl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 26ac63f..218d250 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -151,7 +151,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, if((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "unable to get external file name") - if(*s == NULL) + if(*s == (char)NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "invalid external file name") mesg->slot[u].name = H5MM_xstrdup (s); HDassert(mesg->slot[u].name); -- cgit v0.12 From d7c76e3aacd6f5966725516b0049f62e2efea586 Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Wed, 6 Sep 2017 01:51:06 -0500 Subject: Add info for release notes --- release_docs/RELEASE.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 269c19e..9deaf48 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -121,7 +121,14 @@ Bug Fixes since HDF5-1.8.19 Library ------- - - None + - Fix H5HL_offset_into() + + (1) Fix H5HL_offset_into() to return error when offset exceeds heap data + block size. + (2) Fix other places in the library that call this routine to detect + error routine. + + (HDFFV-10216, VC, 2017/09/05) Parallel Library -- cgit v0.12 From b15011a59af9e70eb06865234f8f0dacab34aa0f Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Thu, 7 Sep 2017 15:59:49 -0500 Subject: Fix for HDFFV-9947 Fix to return error when encoding dataspace selection exceeds 32 bit integer limit. --- src/H5Shyper.c | 55 +++++++++++++++++++++++---------- src/H5Spkg.h | 3 ++ src/H5Spoint.c | 24 +++++++++++++-- test/th5s.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 19 deletions(-) diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 32f6200..09d450f 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -2071,21 +2071,53 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) { const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ - hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */ - hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */ - hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */ - hsize_t temp_off; /* Offset in a given dimension */ + hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */ + hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */ + hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */ + hsize_t bounds_start[H5S_MAX_RANK]; /* Selection bounds */ + hsize_t bounds_end[H5S_MAX_RANK]; /* Selection bounds */ + hsize_t temp_off; /* Offset in a given dimension */ uint8_t *lenp; /* pointer to length location for later storage */ uint32_t len = 0; /* number of bytes used */ hsize_t block_count; /* block counter for regular hyperslabs */ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */ unsigned ndims; /* Rank of the dataspace */ int done; /* Whether we are done with the iteration */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT HDassert(space); + /* Set some convienence values */ + ndims = space->extent.rank; + fast_dim = ndims - 1; + diminfo=space->select.sel_info.hslab->opt_diminfo; + + /* Calculate the # of blocks */ + if(H5S_hyper_is_regular(space)) { + /* Check each dimension */ + for(block_count = 1, u = 0; u < ndims; u++) + block_count *= diminfo[u].count; + } /* end if */ + else + /* Spin through hyperslab spans */ + block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst); + + /* Get bounding box */ + if(H5S_hyper_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Determine whether the number of blocks or the high bounds in the selection exceed (2^32 - 1) */ + if(block_count > H5S_UINT32_MAX) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid number of blocks in selection") + else { + for(u = 0; u < ndims; u++) + if(bounds_end[u] > H5S_UINT32_MAX) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid hyperslab selection") + } + /* Store the preamble information */ UINT32ENCODE(buf, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ UINT32ENCODE(buf, (uint32_t)1); /* Store the version number */ @@ -2101,15 +2133,6 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) if(space->select.sel_info.hslab->diminfo_valid) { unsigned u; /* Local counting variable */ - /* Set some convienence values */ - ndims = space->extent.rank; - fast_dim = ndims - 1; - diminfo=space->select.sel_info.hslab->opt_diminfo; - - /* Check each dimension */ - for(block_count = 1, u = 0; u < ndims; u++) - block_count *= diminfo[u].count; - /* Encode number of hyperslabs */ H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); UINT32ENCODE(buf, (uint32_t)block_count); @@ -2188,7 +2211,6 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) } /* end if */ else { /* Encode number of hyperslabs */ - block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst); H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); UINT32ENCODE(buf, (uint32_t)block_count); len+=4; @@ -2204,7 +2226,8 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) /* Encode length */ UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_serialize() */ diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 2fa872b..0597994 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -46,6 +46,9 @@ * and 'size' callbacks for places to change when updating this. */ #define H5O_SDSPACE_VERSION_LATEST H5O_SDSPACE_VERSION_2 +/* Maximum values for uint16_t and uint32_t */ +#define H5S_UINT16_MAX 65535 /* 2^16 - 1 */ +#define H5S_UINT32_MAX 4294967295 /* 2^32 - 1 */ /* * Dataspace extent information diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 36684ea..e1dbb4d 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -821,12 +821,29 @@ H5S_point_serialize (const H5S_t *space, uint8_t *buf) H5S_pnt_node_t *curr; /* Point information nodes */ uint8_t *lenp; /* pointer to length location for later storage */ uint32_t len=0; /* number of bytes used */ - unsigned u; /* local counting variable */ + unsigned u; /* local counting variable */ + hsize_t bounds_start[H5S_MAX_RANK]; /* Selection bounding box */ + hsize_t bounds_end[H5S_MAX_RANK]; /* Selection bounding box */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT HDassert(space); + /* Get bounding box for the selection */ + HDmemset(bounds_end, 0, sizeof(bounds_end)); + if(H5S_point_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Determine whether the number of points or the high bounds in the selection exceed (2^32 - 1) */ + if(space->select.num_elem > H5S_UINT32_MAX) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid number of points in selection") + else { + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > H5S_UINT32_MAX) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid points selection") + } + /* Store the preamble information */ UINT32ENCODE(buf, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ UINT32ENCODE(buf, (uint32_t)1); /* Store the version number */ @@ -858,7 +875,8 @@ H5S_point_serialize (const H5S_t *space, uint8_t *buf) /* Encode length */ UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_point_serialize() */ diff --git a/test/th5s.c b/test/th5s.c index 98be156..c56f0cc 100644 --- a/test/th5s.c +++ b/test/th5s.c @@ -1317,6 +1317,102 @@ test_h5s_encode(void) /**************************************************************** ** +** test_h5s_encode_exceed32(): +** Verify that encoding selection that exceeds (2^32 - 1) +** (32 bit integer limit) will return error. +** See HDFFV-9947 and the RFC for "H5Sencode/H5Sdecode Format Change" +** +****************************************************************/ +static void +test_h5s_encode_exceed32(void) +{ + hid_t sid; /* Dataspace ID */ + size_t hyper_buf_size=0, pt_buf_size=0; /* Buffer size for H5Sencode */ + unsigned char *hyper_buf=NULL, *pt_buf=NULL; /* Buffers for H5Sencode */ + hsize_t numparticles = 8388608; + unsigned num_dsets = 513; + hsize_t total_particles = numparticles * num_dsets; + hsize_t vdsdims[1] = {total_particles}; + hsize_t start, count, block; /* Hyperslab selection specification */ + hsize_t coord[4]; /* Coordinates for point selection */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Dataspace Encoding Exceeding 32 bits integer limit\n")); + + /*------------------------------------------------------------------------- + * Test encoding and decoding of simple dataspace and hyperslab selection. + *------------------------------------------------------------------------- + */ + + /* Create dataspace */ + sid = H5Screate_simple(1, vdsdims, NULL); + CHECK(sid, FAIL, "H5Screate_simple"); + + start = 0; + block = total_particles; /* 4303355904 (exceeds 2^32) */ + count = 1; + + ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, &start, NULL, &count, &block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Encode data space in a buffer */ + ret = H5Sencode(sid, NULL, &hyper_buf_size); + CHECK(ret, FAIL, "H5Sencode"); + + /* Allocate buffer */ + if(hyper_buf_size > 0) { + hyper_buf = (unsigned char*)HDcalloc((size_t)1, hyper_buf_size); + CHECK(hyper_buf, NULL, "HDcalloc"); + } + + /* H5Sencode should fail because block exceeds (2^32 - 1) */ + H5E_BEGIN_TRY { + ret = H5Sencode(sid, hyper_buf, &hyper_buf_size); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Sencode"); + + /*------------------------------------------------------------------------- + * Test encoding and decoding of simple dataspace and points selection. + *------------------------------------------------------------------------- + */ + + /* Select points in dataspace */ + coord[0] = 5; + coord[1] = 15; + coord[2] = 4294967296; /* 2^32 */ + coord[3] = 19; + ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)4, coord); + CHECK(ret, FAIL, "H5Sselect_elements"); + + /* Encode data space in a buffer */ + ret = H5Sencode(sid, NULL, &pt_buf_size); + CHECK(ret, FAIL, "H5Sencode"); + + /* Allocate buffer */ + if(pt_buf_size > 0) + pt_buf = (unsigned char*)HDcalloc((size_t)1, pt_buf_size); + + /* H5Sencode should fail because coord[2] exceeds (2^32 - 1) */ + H5E_BEGIN_TRY { + ret = H5Sencode(sid, pt_buf, &pt_buf_size); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Sencode"); + + /* Close the dataspace */ + ret = H5Sclose(sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Free the buffers */ + if(hyper_buf) + HDfree(hyper_buf); + if(pt_buf) + HDfree(pt_buf); + +} /* test_h5s_encode_exceed32() */ + +/**************************************************************** +** ** test_h5s_scalar_write(): Test scalar H5S (dataspace) writing code. ** ****************************************************************/ @@ -2384,6 +2480,7 @@ test_h5s(void) test_h5s_null(); /* Test Null dataspace H5S code */ test_h5s_zero_dim(); /* Test dataspace with zero dimension size */ test_h5s_encode(); /* Test encoding and decoding */ + test_h5s_encode_exceed32(); /* Testing encoding when selection exceeds 32 bits limit */ test_h5s_scalar_write(); /* Test scalar H5S writing code */ test_h5s_scalar_read(); /* Test scalar H5S reading code */ -- cgit v0.12