From 07e94155a7d456d663fe19a38851556117b5e315 Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Mon, 1 May 2023 16:24:14 -0700 Subject: Harden H5O cache deserialize calls (#2856) --- src/H5Ocache.c | 532 +++++++++++++++++++++++++-------------------------------- 1 file changed, 237 insertions(+), 295 deletions(-) diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 42d8f35..72261fa 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -13,10 +13,8 @@ /*------------------------------------------------------------------------- * * Created: H5Ocache.c - * Sep 28 2005 - * Quincey Koziol * - * Purpose: Object header metadata cache virtual functions. + * Purpose: Object header metadata cache virtual functions * *------------------------------------------------------------------------- */ @@ -30,13 +28,13 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free lists */ -#include "H5MFprivate.h" /* File memory management */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5Opkg.h" /* Object headers */ -#include "H5WBprivate.h" /* Wrapped Buffers */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ +#include "H5WBprivate.h" /* Wrapped Buffers */ /****************/ /* Local Macros */ @@ -74,7 +72,7 @@ static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing); static herr_t H5O__cache_chk_free_icr(void *thing); /* Prefix routines */ -static herr_t H5O__prefix_deserialize(const uint8_t *image, H5O_cache_ud_t *udata); +static herr_t H5O__prefix_deserialize(const uint8_t *image, size_t len, H5O_cache_ud_t *udata); /* Chunk routines */ static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t *image, @@ -144,15 +142,10 @@ H5FL_SEQ_DEFINE(H5O_cont_t); /*------------------------------------------------------------------------- * Function: H5O__cache_get_initial_load_size() * - * Purpose: Tell the metadata cache how much data to read from file in - * the first speculative read for the object header. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Tell the metadata cache how much data to read from file in + * the first speculative read for the object header. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t @@ -160,7 +153,6 @@ H5O__cache_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len) { FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(image_len); /* Set the image length size */ @@ -172,33 +164,26 @@ H5O__cache_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len) /*------------------------------------------------------------------------- * Function: H5O__cache_get_final_load_size() * - * Purpose: Tell the metadata cache the final size of an object header. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * November 18, 2016 + * Purpose: Tell the metadata cache the final size of an object header. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t -H5O__cache_get_final_load_size(const void *image, size_t H5_ATTR_NDEBUG_UNUSED image_len, void *_udata, - size_t *actual_len) +H5O__cache_get_final_load_size(const void *image, size_t image_len, void *_udata, size_t *actual_len) { H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(image); HDassert(udata); HDassert(actual_len); HDassert(*actual_len == image_len); /* Deserialize the object header prefix */ - if (H5O__prefix_deserialize((const uint8_t *)image, udata) < 0) + if (H5O__prefix_deserialize((const uint8_t *)image, image_len, udata) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't deserialize object header prefix") /* Sanity check */ @@ -219,10 +204,6 @@ done: * * Return: Success: TRUE/FALSE * Failure: Negative - * - * Programmer: Vailin Choi - * Aug 2015 - * *------------------------------------------------------------------------- */ static htri_t @@ -230,11 +211,10 @@ H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata) { const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ - htri_t ret_value = TRUE; /* Return value */ + htri_t ret_value = TRUE; FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(image); HDassert(udata); HDassert(udata->oh); @@ -257,8 +237,8 @@ H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata) in H5O__prefix_deserialize() */ udata->free_oh = TRUE; ret_value = FALSE; - } /* end if */ - } /* end if */ + } + } else HDassert(!(udata->common.file_intent & H5F_ACC_SWMR_WRITE)); @@ -268,21 +248,18 @@ H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata) /*------------------------------------------------------------------------- * Function: H5O__cache_deserialize * - * Purpose: Attempt to deserialize the object header contained in the - * supplied buffer, load the data into an instance of H5O_t, and - * return a pointer to the new instance. + * Purpose: Attempt to deserialize the object header contained in the + * supplied buffer, load the data into an instance of H5O_t, and + * return a pointer to the new instance. * - * Note that the object header is read with with a speculative read. - * If the initial read is too small, make note of this fact and return - * without error. H5C__load_entry() will note the size discrepancy - * and retry the deserialize operation with the correct size read. + * Note that the object header is read with with a speculative + * read. If the initial read is too small, make note of this fact + * and return without error. H5C__load_entry() will note the + * size discrepancy and retry the deserialize operation with + * the correct size read. * * Return: Success: Pointer to in core representation * Failure: NULL - * - * Programmer: John Mainzer - * 7/28/14 - * *------------------------------------------------------------------------- */ static void * @@ -290,11 +267,10 @@ H5O__cache_deserialize(const void *image, size_t len, void *_udata, hbool_t *dir { H5O_t *oh = NULL; /* Object header read in */ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ - void *ret_value = NULL; /* Return value */ + void *ret_value = NULL; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(image); HDassert(len > 0); HDassert(udata); @@ -302,19 +278,18 @@ H5O__cache_deserialize(const void *image, size_t len, void *_udata, hbool_t *dir HDassert(udata->common.cont_msg_info); HDassert(dirty); - /* Check for partially deserialized object header */ - /* (Object header prefix will be deserialized if the object header came - * through the 'get_final_load_size' callback and not deserialized if - * the object header is coming from a cache image - QAK, 2016/12/14) + /* Check for partially deserialized object header + * + * The Object header prefix will be deserialized if the object header came + * through the 'get_final_load_size' callback and not deserialized if + * the object header is coming from a cache image. */ if (NULL == udata->oh) { /* Deserialize the object header prefix */ - if (H5O__prefix_deserialize((const uint8_t *)image, udata) < 0) + if (H5O__prefix_deserialize((const uint8_t *)image, len, udata) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't deserialize object header prefix") - - /* Sanity check */ HDassert(udata->oh); - } /* end if */ + } /* Retrieve partially deserialized object header from user data */ oh = udata->oh; @@ -327,7 +302,7 @@ H5O__cache_deserialize(const void *image, size_t len, void *_udata, hbool_t *dir /* Create virtual entry, for use as proxy */ if (NULL == (oh->proxy = H5AC_proxy_entry_create())) HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy") - } /* end if */ + } else oh->proxy = NULL; @@ -354,16 +329,11 @@ done: /*------------------------------------------------------------------------- * Function: H5O__cache_image_len * - * Purpose: Compute the size in bytes of the specified instance of - * H5O_t on disk, and return it in *image_len. On failure, - * the value of *image_len is undefined. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Compute the size in bytes of the specified instance of + * H5O_t on disk, and return it in *image_len. On failure, + * the value of *image_len is undefined. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t @@ -373,7 +343,6 @@ H5O__cache_image_len(const void *_thing, size_t *image_len) FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(oh); HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(oh->cache_info.type == H5AC_OHDR); @@ -388,15 +357,10 @@ H5O__cache_image_len(const void *_thing, size_t *image_len) /*------------------------------------------------------------------------- * Function: H5O__cache_serialize * - * Purpose: Serialize the contents of the supplied object header, and - * load this data into the supplied buffer. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Serialize the contents of the supplied object header, and + * load this data into the supplied buffer. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t @@ -404,11 +368,10 @@ H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing) { H5O_t *oh = (H5O_t *)_thing; /* Object header to encode */ uint8_t *chunk_image; /* Pointer to object header prefix buffer */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(f); HDassert(image); HDassert(oh); @@ -451,13 +414,13 @@ H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing) UINT32ENCODE(chunk_image, oh->mtime); UINT32ENCODE(chunk_image, oh->ctime); UINT32ENCODE(chunk_image, oh->btime); - } /* end if */ + } /* Attribute fields */ if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) { UINT16ENCODE(chunk_image, oh->max_compact); UINT16ENCODE(chunk_image, oh->min_dense); - } /* end if */ + } /* First chunk size */ switch (oh->flags & H5O_HDR_CHUNK0_SIZE) { @@ -483,8 +446,8 @@ H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing) default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0") - } /* end switch */ - } /* end if */ + } + } else { /* Version */ *chunk_image++ = oh->version; @@ -509,7 +472,7 @@ H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing) /* Zero to alignment */ HDmemset(chunk_image, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12)); chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - 12); - } /* end else */ + } HDassert((size_t)(chunk_image - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); @@ -533,24 +496,17 @@ done: * * Purpose: Handle cache action notifications * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Jul 23 2016 - * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__cache_notify(H5AC_notify_action_t action, void *_thing) { H5O_t *oh = (H5O_t *)_thing; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* - * Check arguments. - */ HDassert(oh); switch (action) { @@ -563,12 +519,12 @@ H5O__cache_notify(H5AC_notify_action_t action, void *_thing) /* Register the object header as a parent of the virtual entry */ if (H5AC_proxy_entry_add_parent(oh->proxy, oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add object header as parent of proxy") - } /* end if */ + } break; case H5AC_NOTIFY_ACTION_AFTER_FLUSH: case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED: - /* do nothing */ + /* Do nothing */ break; case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: { @@ -578,17 +534,17 @@ H5O__cache_notify(H5AC_notify_action_t action, void *_thing) for (u = 0; u < oh->nmesgs; u++) if (oh->mesg[u].chunkno == 0) oh->mesg[u].dirty = FALSE; -#ifndef NDEBUG +#ifdef H5O_DEBUG /* Reset the number of messages dirtied by decoding */ oh->ndecode_dirtied = 0; -#endif /* NDEBUG */ +#endif } break; case H5AC_NOTIFY_ACTION_CHILD_DIRTIED: case H5AC_NOTIFY_ACTION_CHILD_CLEANED: case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED: case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED: - /* do nothing */ + /* Do nothing */ break; case H5AC_NOTIFY_ACTION_BEFORE_EVICT: @@ -596,12 +552,12 @@ H5O__cache_notify(H5AC_notify_action_t action, void *_thing) /* Unregister the object header as a parent of the virtual entry */ if (H5AC_proxy_entry_remove_parent(oh->proxy, oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't remove object header as parent of proxy") - } /* end if */ + } break; default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache") - } /* end switch */ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -610,29 +566,23 @@ done: /*------------------------------------------------------------------------- * Function: H5O__cache_free_icr * - * Purpose: Free the in core representation of the supplied object header. - * - * Note: The metadata cache sets the object's cache_info.magic to - * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr - * callback (checked in assert). + * Purpose: Free the in core representation of the supplied object header. * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Note: The metadata cache sets the object's cache_info.magic to + * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr + * callback (checked in assert). * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__cache_free_icr(void *_thing) { H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(oh); HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); HDassert(oh->cache_info.type == H5AC_OHDR); @@ -648,16 +598,11 @@ done: /*------------------------------------------------------------------------- * Function: H5O__cache_chk_get_initial_load_size() * - * Purpose: Tell the metadata cache how large the on disk image of the - * chunk proxy is, so it can load the image into a buffer for the - * deserialize call. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Tell the metadata cache how large the on disk image of the + * chunk proxy is, so it can load the image into a buffer for the + * deserialize call. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t @@ -667,7 +612,6 @@ H5O__cache_chk_get_initial_load_size(void *_udata, size_t *image_len) FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(udata); HDassert(udata->oh); HDassert(image_len); @@ -686,10 +630,6 @@ H5O__cache_chk_get_initial_load_size(void *_udata, size_t *image_len) * * Return: Success: TRUE/FALSE * Failure: Negative - * - * Programmer: Vailin Choi - * Aug 2015 - * *------------------------------------------------------------------------- */ static htri_t @@ -697,11 +637,10 @@ H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata) { const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */ - htri_t ret_value = TRUE; /* Return value */ + htri_t ret_value = TRUE; FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(image); /* There is no checksum for version 1 */ @@ -714,7 +653,7 @@ H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata) if (stored_chksum != computed_chksum) ret_value = FALSE; - } /* end if */ + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_verify_chksum() */ @@ -722,16 +661,12 @@ H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata) /*------------------------------------------------------------------------- * Function: H5O__cache_chk_deserialize * - * Purpose: Attempt to deserialize the object header continuation chunk - * contained in the supplied buffer, load the data into an instance - * of H5O_chunk_proxy_t, and return a pointer to the new instance. + * Purpose: Attempt to deserialize the object header continuation chunk + * contained in the supplied buffer, load the data into an instance + * of H5O_chunk_proxy_t, and return a pointer to the new instance. * * Return: Success: Pointer to in core representation * Failure: NULL - * - * Programmer: John Mainzer - * 7/28/14 - * *------------------------------------------------------------------------- */ static void * @@ -739,11 +674,10 @@ H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata, hbool_t { H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */ - void *ret_value = NULL; /* Return value */ + void *ret_value = NULL; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(image); HDassert(len > 0); HDassert(udata); @@ -757,7 +691,6 @@ H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata, hbool_t /* Check if we are still decoding the object header */ /* (as opposed to bringing a piece of it back from the file) */ if (udata->decoding) { - /* Sanity check */ HDassert(udata->common.f); HDassert(udata->common.cont_msg_info); @@ -768,7 +701,7 @@ H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata, hbool_t /* Set the chunk number for the chunk proxy */ H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t); - } /* end if */ + } else { /* Sanity check */ HDassert(udata->chunkno < udata->oh->nchunks); @@ -781,7 +714,7 @@ H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata, hbool_t */ HDassert(0 == HDmemcmp(image, udata->oh->chunk[chk_proxy->chunkno].image, udata->oh->chunk[chk_proxy->chunkno].size)); - } /* end else */ + } /* Increment reference count of object header */ if (H5O__inc_rc(udata->oh) < 0) @@ -802,15 +735,10 @@ done: /*------------------------------------------------------------------------- * Function: H5O__cache_chk_image_len * - * Purpose: Return the on disk image size of a object header chunk to the - * metadata cache via the image_len. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Return the on disk image size of a object header chunk to the + * metadata cache via the image_len. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t @@ -820,7 +748,6 @@ H5O__cache_chk_image_len(const void *_thing, size_t *image_len) FUNC_ENTER_PACKAGE_NOERR - /* Check arguments */ HDassert(chk_proxy); HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK); @@ -835,28 +762,22 @@ H5O__cache_chk_image_len(const void *_thing, size_t *image_len) /*------------------------------------------------------------------------- * Function: H5O__cache_chk_serialize * - * Purpose: Given a pointer to an instance of an object header chunk and an - * appropriately sized buffer, serialize the contents of the - * instance for writing to disk, and copy the serialized data - * into the buffer. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: John Mainzer - * 7/28/14 + * Purpose: Given a pointer to an instance of an object header chunk and an + * appropriately sized buffer, serialize the contents of the + * instance for writing to disk, and copy the serialized data + * into the buffer. * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *_thing) { H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to serialize */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(f); HDassert(image); HDassert(chk_proxy); @@ -883,24 +804,17 @@ done: * * Purpose: Handle cache action notifications * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Neil Fortner - * Mar 20 2012 - * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) { H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* - * Check arguments. - */ HDassert(chk_proxy); HDassert(chk_proxy->oh); @@ -922,13 +836,13 @@ H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) */ if (H5AC_create_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") - } /* end if */ + } /* Add flush dependency on object header */ { if (H5AC_create_flush_dependency(chk_proxy->oh, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") - } /* end if */ + } /* Add flush dependency on object header proxy, if proxy exists */ { @@ -940,12 +854,12 @@ H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add object header chunk as parent of proxy") } - } /* end if */ + } break; case H5AC_NOTIFY_ACTION_AFTER_FLUSH: case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED: - /* do nothing */ + /* Do nothing */ break; case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: { @@ -961,7 +875,7 @@ H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) case H5AC_NOTIFY_ACTION_CHILD_CLEANED: case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED: case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED: - /* do nothing */ + /* Do nothing */ break; case H5AC_NOTIFY_ACTION_BEFORE_EVICT: @@ -978,7 +892,7 @@ H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) if (H5AC_destroy_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency") chk_proxy->fd_parent = NULL; - } /* end if */ + } /* Unregister the object header as a parent of the virtual entry */ if (H5AC_destroy_flush_dependency(chk_proxy->oh, chk_proxy) < 0) @@ -988,16 +902,12 @@ H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) if (H5AC_proxy_entry_remove_parent(chk_proxy->oh->proxy, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't remove object header chunk as parent of proxy") - } /* end if */ + } break; default: -#ifdef NDEBUG HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache") -#else /* NDEBUG */ - HDassert(0 && "Unknown action?!?"); -#endif /* NDEBUG */ - } /* end switch */ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1006,30 +916,24 @@ done: /*------------------------------------------------------------------------- * Function: H5O__cache_chk_free_icr * - * Purpose: Free the in core memory associated with the supplied object - * header continuation chunk. - * - * Note: The metadata cache sets the object's cache_info.magic to - * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr - * callback (checked in assert). - * - * Return: Success: SUCCEED - * Failure: FAIL + * Purpose: Free the in core memory associated with the supplied object + * header continuation chunk. * - * Programmer: John Mainzer - * 7/28/14 + * Note: The metadata cache sets the object's cache_info.magic to + * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr + * callback (checked in assert). * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_free_icr(void *_thing) { H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(chk_proxy); HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK); @@ -1045,26 +949,20 @@ done: /*------------------------------------------------------------------------- * Function: H5O__add_cont_msg * - * Purpose: Add information from a continuation message to the list of + * Purpose: Add information from a continuation message to the list of * continuation messages in the object header * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * July 12, 2008 - * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont) { - size_t contno; /* Continuation message index */ - herr_t ret_value = SUCCEED; /* Return value */ + size_t contno; /* Continuation message index */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(cont_msg_info); HDassert(cont); @@ -1077,7 +975,7 @@ H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont) HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") cont_msg_info->alloc_nmsgs = na; cont_msg_info->msgs = x; - } /* end if */ + } /* Init the continuation message info */ contno = cont_msg_info->nmsgs++; @@ -1092,26 +990,21 @@ done: /*------------------------------------------------------------------------- * Function: H5O__prefix_deserialize() * - * Purpose: Deserialize an object header prefix - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * December 14, 2016 + * Purpose: Deserialize an object header prefix * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t -H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) +H5O__prefix_deserialize(const uint8_t *_image, size_t len, H5O_cache_ud_t *udata) { const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ + const uint8_t *p_end = image + len - 1; /* End of image buffer */ H5O_t *oh = NULL; /* Object header read in */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(image); HDassert(udata); @@ -1125,16 +1018,23 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) /* Check for presence of magic number */ /* (indicates version 2 or later) */ + if (H5_IS_BUFFER_OVERFLOW(image, H5_SIZEOF_MAGIC, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); if (!HDmemcmp(image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { - /* Magic number */ + + /* Magic number (bounds checked above) */ image += H5_SIZEOF_MAGIC; /* Version */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); oh->version = *image++; if (H5O_VERSION_2 != oh->version) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") /* Flags */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); oh->flags = *image++; if (oh->flags & ~H5O_HDR_ALL_FLAGS) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)") @@ -1144,7 +1044,10 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) /* Time fields */ if (oh->flags & H5O_HDR_STORE_TIMES) { - uint32_t tmp; /* Temporary value */ + uint32_t tmp; + + if (H5_IS_BUFFER_OVERFLOW(image, 4 + 4 + 4 + 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(image, tmp); oh->atime = (time_t)tmp; @@ -1154,48 +1057,61 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) oh->ctime = (time_t)tmp; UINT32DECODE(image, tmp); oh->btime = (time_t)tmp; - } /* end if */ + } else oh->atime = oh->mtime = oh->ctime = oh->btime = 0; /* Attribute fields */ if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) { + if (H5_IS_BUFFER_OVERFLOW(image, 2 + 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); + UINT16DECODE(image, oh->max_compact); UINT16DECODE(image, oh->min_dense); if (oh->max_compact < oh->min_dense) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values") - } /* end if */ + } else { oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF; oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF; - } /* end else */ + } /* First chunk size */ switch (oh->flags & H5O_HDR_CHUNK0_SIZE) { case 0: /* 1 byte size */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); udata->chunk0_size = *image++; break; case 1: /* 2 byte size */ + if (H5_IS_BUFFER_OVERFLOW(image, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(image, udata->chunk0_size); break; case 2: /* 4 byte size */ + if (H5_IS_BUFFER_OVERFLOW(image, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(image, udata->chunk0_size); break; case 3: /* 8 byte size */ + if (H5_IS_BUFFER_OVERFLOW(image, 8, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT64DECODE(image, udata->chunk0_size); break; default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0") - } /* end switch */ + } if (udata->chunk0_size > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") - } /* end if */ + } else { /* Version */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); oh->version = *image++; if (H5O_VERSION_1 != oh->version) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") @@ -1204,12 +1120,18 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) oh->flags = H5O_CRT_OHDR_FLAGS_DEF; /* Reserved */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); image++; /* Number of messages */ + if (H5_IS_BUFFER_OVERFLOW(image, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(image, udata->v1_pfx_nmesgs); /* Link count */ + if (H5_IS_BUFFER_OVERFLOW(image, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(image, oh->nlink); /* Reset unused time fields */ @@ -1220,21 +1142,27 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) oh->min_dense = 0; /* First chunk size */ + if (H5_IS_BUFFER_OVERFLOW(image, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(image, udata->chunk0_size); if ((udata->v1_pfx_nmesgs > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) || (udata->v1_pfx_nmesgs == 0 && udata->chunk0_size > 0)) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") /* Reserved, in version 1 (for 8-byte alignment padding) */ + if (H5_IS_BUFFER_OVERFLOW(image, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); image += 4; - } /* end else */ + } /* Verify object header prefix length */ - HDassert((size_t)(image - _image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); + if ((size_t)(image - _image) != (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))) + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header prefix length") /* If udata->oh is to be freed (see H5O__cache_verify_chksum), - save the pointer to udata->oh and free it later after setting - udata->oh with the new object header */ + * save the pointer to udata->oh and free it later after setting + * udata->oh with the new object header + */ if (udata->free_oh) { H5O_t *saved_oh = udata->oh; HDassert(udata->oh); @@ -1263,34 +1191,27 @@ done: /*------------------------------------------------------------------------- * Function: H5O__chunk_deserialize * - * Purpose: Deserialize a chunk for an object header - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * July 12, 2008 + * Purpose: Deserialize a chunk for an object header * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t *image, size_t len, H5O_common_cache_ud_t *udata, hbool_t *dirty) { - const uint8_t *chunk_image; /* Pointer into buffer to decode */ + const uint8_t *chunk_image = NULL; /* Pointer into buffer to decode */ + const uint8_t *p_end = NULL; /* End of image buffer */ uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */ unsigned merged_null_msgs = 0; /* Number of null messages merged together */ unsigned chunkno; /* Current chunk's index */ -#ifndef NDEBUG - unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */ -#endif /* NDEBUG */ - hbool_t mesgs_modified = + unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */ + hbool_t mesgs_modified = FALSE; /* Whether any messages were modified when the object header was deserialized */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(oh); HDassert(H5F_addr_defined(addr)); HDassert(image); @@ -1307,7 +1228,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed") oh->alloc_nchunks = na; oh->chunk = x; - } /* end if */ + } /* Init the chunk data info */ chunkno = (unsigned)oh->nchunks++; @@ -1329,24 +1250,31 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* Point into chunk image to decode */ chunk_image = oh->chunk[chunkno].image; + p_end = chunk_image + oh->chunk[chunkno].size - 1; + + /* Skip over [already decoded] prefix in special case of chunk 0 */ + if (chunkno == 0) { + size_t skip = (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)); + + if (H5_IS_BUFFER_OVERFLOW(chunk_image, skip, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); + chunk_image += skip; + } - /* Handle chunk 0 as special case */ - if (chunkno == 0) - /* Skip over [already decoded] prefix */ - chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)); /* Check for magic # on chunks > 0 in later versions of the format */ else if (chunkno > 0 && oh->version > H5O_VERSION_1) { /* Magic number */ - if (HDmemcmp(chunk_image, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0) + if (H5_IS_BUFFER_OVERFLOW(chunk_image, H5_SIZEOF_MAGIC, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); + if (HDmemcmp(chunk_image, H5O_CHK_MAGIC, H5_SIZEOF_MAGIC) != 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "wrong object header chunk signature") chunk_image += H5_SIZEOF_MAGIC; - } /* end if */ + } /* Decode messages from this chunk */ eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)); -#ifndef NDEBUG nullcnt = 0; -#endif /* NDEBUG */ + while (chunk_image < eom_ptr) { size_t mesg_size; /* Size of message read in */ unsigned id; /* ID (type) of current message */ @@ -1356,17 +1284,27 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* Decode message prefix info */ /* Version # */ - if (oh->version == H5O_VERSION_1) + if (oh->version == H5O_VERSION_1) { + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(chunk_image, id) - else + } + else { + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); id = *chunk_image++; + } /* Message size */ + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(chunk_image, mesg_size); if (mesg_size != H5O_ALIGN_OH(oh, mesg_size)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message not aligned") /* Message flags */ + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); flags = *chunk_image++; if (flags & ~H5O_MSG_FLAG_BITS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unknown flag for message") @@ -1381,13 +1319,20 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t * knows about */ /* Reserved bytes/creation index */ - if (oh->version == H5O_VERSION_1) - chunk_image += 3; /*reserved*/ + if (oh->version == H5O_VERSION_1) { + /* Reserved bytes */ + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 3, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); + chunk_image += 3; + } else { /* Only decode creation index if they are being tracked */ - if (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) + if (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) { + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(chunk_image, crt_idx); - } /* end else */ + } + } /* Try to detect invalidly formatted object header message that * extends past end of chunk. @@ -1395,11 +1340,9 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t if (chunk_image + mesg_size > eom_ptr) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "corrupt object header") -#ifndef NDEBUG /* Increment count of null messages */ if (H5O_NULL_ID == id) nullcnt++; -#endif /* NDEBUG */ /* Check for combining two adjacent 'null' messages */ if ((udata->file_intent & H5F_ACC_RDWR) && H5O_NULL_ID == id && oh->nmesgs > 0 && @@ -1412,7 +1355,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t oh->mesg[mesgno].raw_size += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size; oh->mesg[mesgno].dirty = TRUE; merged_null_msgs++; - } /* end if */ + } else { H5O_mesg_t *mesg; /* Pointer to new message */ unsigned ioflags = 0; /* Flags for decode routine */ @@ -1476,20 +1419,20 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* This is a bit aggressive, since the application may * never change anything about the object (metadata or * raw data), but we can sort out the finer details - * when/if we start using the flag - QAK + * when/if we start using the flag. */ /* Also, it's possible that this functionality may not * get invoked if the object header is brought into * the metadata cache in some other "weird" way, like - * using H5Ocopy() - QAK + * using H5Ocopy(). */ mesg->flags |= H5O_MSG_FLAG_WAS_UNKNOWN; /* Mark the message and chunk as dirty */ mesg->dirty = TRUE; mesgs_modified = TRUE; - } /* end if */ - } /* end if */ + } + } else { /* Check for message of unshareable class marked as "shareable" */ @@ -1500,7 +1443,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* Set message class for "known" messages */ mesg->type = H5O_msg_class_g[id]; - } /* end else */ + } /* Do some inspection/interpretation of new messages from this chunk */ /* (detect continuation messages, ref. count messages, etc.) */ @@ -1522,7 +1465,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* Add to continuation messages left to interpret */ if (H5O__add_cont_msg(udata->cont_msg_info, cont) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add continuation message") - } /* end if */ + } /* Check if message is a ref. count message */ else if (H5O_REFCOUNT_ID == id) { H5O_refcount_t *refcount; @@ -1542,24 +1485,24 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t if (!refcount) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't decode refcount") oh->nlink = *refcount; - } /* end if */ + } /* Check if message is a link message */ else if (H5O_LINK_ID == id) { /* Increment the count of link messages */ oh->link_msgs_seen++; - } /* end if */ + } /* Check if message is an attribute message */ else if (H5O_ATTR_ID == id) { /* Increment the count of attribute messages */ oh->attr_msgs_seen++; - } /* end if */ + } /* Mark the message & chunk as dirty if the message was changed by decoding */ if ((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) { mesg->dirty = TRUE; mesgs_modified = TRUE; - } /* end if */ - } /* end else */ + } + } /* Advance decode pointer past message */ chunk_image += mesg_size; @@ -1567,18 +1510,20 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* Check for 'gap' at end of chunk */ if ((eom_ptr - chunk_image) > 0 && (eom_ptr - chunk_image) < H5O_SIZEOF_MSGHDR_OH(oh)) { /* Gaps can only occur in later versions of the format */ - HDassert(oh->version > H5O_VERSION_1); + if (oh->version == H5O_VERSION_1) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "gap found in early version of file format"); /* Gaps should only occur in chunks with no null messages */ - HDassert(nullcnt == 0); + if (nullcnt != 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "gap in chunk with no null messages"); /* Set gap information for chunk */ oh->chunk[chunkno].gap = (size_t)(eom_ptr - chunk_image); /* Increment location in chunk */ chunk_image += oh->chunk[chunkno].gap; - } /* end if */ - } /* end while */ + } + } /* Check for correct checksum on chunks, in later versions of the format */ if (oh->version > H5O_VERSION_1) { @@ -1587,11 +1532,14 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t /* checksum verification already done in verify_chksum cb */ /* Metadata checksum */ + if (H5_IS_BUFFER_OVERFLOW(chunk_image, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(chunk_image, stored_chksum); - } /* end if */ + } - /* Sanity check */ - HDassert(chunk_image == oh->chunk[chunkno].image + oh->chunk[chunkno].size); + /* Size check */ + if (chunk_image != oh->chunk[chunkno].image + oh->chunk[chunkno].size) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "object header image size mismatch"); /* Mark the chunk dirty if we've modified messages */ if (mesgs_modified) @@ -1601,7 +1549,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t if (merged_null_msgs > 0) { udata->merged_null_msgs += merged_null_msgs; *dirty = TRUE; - } /* end if */ + } done: if (ret_value < 0 && udata->cont_msg_info->msgs) { @@ -1612,28 +1560,22 @@ done: } /* H5O__chunk_deserialize() */ /*------------------------------------------------------------------------- - * Function: H5O__chunk_serialize + * Function: H5O__chunk_serialize * - * Purpose: Serialize a chunk for an object header - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * July 12, 2008 + * Purpose: Serialize a chunk for an object header * + * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno) { - H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE - /* Check arguments */ HDassert(f); HDassert(oh); @@ -1673,7 +1615,7 @@ H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno) /* Metadata checksum */ chunk_image = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM); UINT32ENCODE(chunk_image, metadata_chksum); - } /* end if */ + } done: FUNC_LEAVE_NOAPI(ret_value) -- cgit v0.12