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: [PATCH] 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 42d8f3590e..72261faa80 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.
+ * 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).
- *
- * 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.
+ * 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
- *
- * 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)