From b1a6873b1021c967b661727edae9de87d194f744 Mon Sep 17 00:00:00 2001
From: Dana Robinson <derobins@hdfgroup.org>
Date: Mon, 26 Feb 2018 18:31:40 -0800
Subject: [PATCH] CVE-2017-17506

---
 src/H5Abtree2.c      |   4 +-
 src/H5Adense.c       |   4 +-
 src/H5Gbtree2.c      |   4 +-
 src/H5Gdense.c       |  20 +--
 src/H5HFcache.c      |   2 +-
 src/H5Oainfo.c       |   5 +-
 src/H5Oattr.c        |   8 +-
 src/H5Obogus.c       |   5 +-
 src/H5Obtreek.c      |   5 +-
 src/H5Ocache_image.c | 377 +++++++++++++++++++++++++++++++++++++++
 src/H5Ocont.c        |   5 +-
 src/H5Odrvinfo.c     |   5 +-
 src/H5Odtype.c       |   4 +-
 src/H5Oefl.c         |   5 +-
 src/H5Ofill.c        |  10 +-
 src/H5Ofsinfo.c      | 408 +++++++++++++++++++++++++++++++++++++++++++
 src/H5Oginfo.c       |   5 +-
 src/H5Olayout.c      |   5 +-
 src/H5Olinfo.c       |   5 +-
 src/H5Olink.c        |   5 +-
 src/H5Omessage.c     |   4 +-
 src/H5Omtime.c       |  10 +-
 src/H5Oname.c        |   5 +-
 src/H5Opkg.h         |   4 +-
 src/H5Opline.c       |  51 +++---
 src/H5Oprivate.h     |   2 +-
 src/H5Orefcount.c    |   5 +-
 src/H5Osdspace.c     |   5 +-
 src/H5Oshared.c      |   2 +-
 src/H5Oshared.h      |   8 +-
 src/H5Oshmesg.c      |   5 +-
 src/H5Ostab.c        |   5 +-
 src/H5S.c            |   2 +-
 src/H5SM.c           |  16 +-
 src/H5T.c            |  13 +-
 src/H5Tprivate.h     |   2 +
 36 files changed, 926 insertions(+), 104 deletions(-)
 create mode 100644 src/H5Ocache_image.c
 create mode 100644 src/H5Ofsinfo.c

diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index 33a031e6f1..02fffce21c 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -162,7 +162,7 @@ const H5B2_class_t H5A_BT2_CORDER[1]={{ /* B-tree class information */
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5A_dense_fh_name_cmp(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5A__dense_fh_name_cmp(const void *obj, size_t obj_len, void *_udata)
 {
     H5A_fh_ud_cmp_t *udata = (H5A_fh_ud_cmp_t *)_udata;         /* User data for 'op' callback */
     H5A_t *attr = NULL;                 /* Pointer to attribute created from heap object */
@@ -172,7 +172,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_uda
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode attribute information */
-    if(NULL == (attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_ATTR_ID, (const unsigned char *)obj)))
+    if(NULL == (attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_ATTR_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode attribute")
 
     /* Compare the string values */
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 291f422c62..ab159ff5e8 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -843,7 +843,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5A__dense_copy_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5A__dense_copy_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5A_fh_ud_cp_t *udata = (H5A_fh_ud_cp_t *)_udata;       /* User data for fractal heap 'op' callback */
     herr_t ret_value = SUCCEED;   /* Return value */
@@ -857,7 +857,7 @@ H5A__dense_copy_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_uda
      *  HDF5 routine, it could attempt to re-protect that direct block for the
      *  heap, causing the HDF5 routine called to fail)
      */
-    if(NULL == (udata->attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_ATTR_ID, (const unsigned char *)obj)))
+    if(NULL == (udata->attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_ATTR_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
 
     /* Set the creation order index for the attribute */
diff --git a/src/H5Gbtree2.c b/src/H5Gbtree2.c
index 888c611d77..d520484890 100644
--- a/src/H5Gbtree2.c
+++ b/src/H5Gbtree2.c
@@ -159,7 +159,7 @@ const H5B2_class_t H5G_BT2_CORDER[1]={{ /* B-tree class information */
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_fh_name_cmp(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_fh_name_cmp(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_cmp_t *udata = (H5G_fh_ud_cmp_t *)_udata;         /* User data for 'op' callback */
     H5O_link_t *lnk;    /* Pointer to link created from heap object */
@@ -168,7 +168,7 @@ H5G_dense_fh_name_cmp(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_uda
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode link information */
-    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
 
     /* Compare the string values */
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index 9ec895187d..a43939eb97 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -597,7 +597,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_lookup_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_lookup_by_idx_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_lbi_t *udata = (H5G_fh_ud_lbi_t *)_udata;       /* User data for fractal heap 'op' callback */
     H5O_link_t *tmp_lnk = NULL;         /* Temporary pointer to link */
@@ -606,7 +606,7 @@ H5G_dense_lookup_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, vo
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode link information & keep a copy */
-    if(NULL == (tmp_lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (tmp_lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
 
     /* Copy link information */
@@ -887,7 +887,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_iterate_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_iterate_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_it_t *udata = (H5G_fh_ud_it_t *)_udata;       /* User data for fractal heap 'op' callback */
     herr_t ret_value = SUCCEED;   /* Return value */
@@ -901,7 +901,7 @@ H5G_dense_iterate_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_u
      *  HDF5 routine, it could attempt to re-protect that direct block for the
      *  heap, causing the HDF5 routine called to fail - QAK)
      */
-    if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
 
 done:
@@ -1099,7 +1099,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_get_name_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_get_name_by_idx_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_gnbi_t *udata = (H5G_fh_ud_gnbi_t *)_udata;       /* User data for fractal heap 'op' callback */
     H5O_link_t *lnk;            /* Pointer to link created from heap object */
@@ -1108,7 +1108,7 @@ H5G_dense_get_name_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len,
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode link information */
-    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
 
     /* Get the length of the name */
@@ -1306,7 +1306,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_remove_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_remove_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_rm_t *udata = (H5G_fh_ud_rm_t *)_udata;       /* User data for fractal heap 'op' callback */
     H5O_link_t *lnk = NULL;             /* Pointer to link created from heap object */
@@ -1316,7 +1316,7 @@ H5G_dense_remove_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_ud
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode link information */
-    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
 
     /* Check for removing the link from the creation order index */
@@ -1483,7 +1483,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5G_dense_remove_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata)
+H5G_dense_remove_by_idx_fh_cb(const void *obj, size_t obj_len, void *_udata)
 {
     H5G_fh_ud_rmbi_t *udata = (H5G_fh_ud_rmbi_t *)_udata;       /* User data for fractal heap 'op' callback */
     herr_t ret_value = SUCCEED; /* Return value */
@@ -1491,7 +1491,7 @@ H5G_dense_remove_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, vo
     FUNC_ENTER_NOAPI_NOINIT
 
     /* Decode link information */
-    if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj)))
+    if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, obj_len, (const unsigned char *)obj)))
         HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, H5_ITER_ERROR, "can't decode link")
 
     /* Can't operate on link here because the fractal heap block is locked */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index f0d251c8de..319a865438 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -384,7 +384,7 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
         UINT32DECODE(p, hdr->pline_root_direct_filter_mask);
 
         /* Decode I/O filter information */
-        if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, udata->dxpl_id, NULL, H5O_PLINE_ID, p)))
+        if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, udata->dxpl_id, NULL, H5O_PLINE_ID, len, image)))
             HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
         p += hdr->filter_len;
 
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index e85df44262..5aab4c6c32 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -34,7 +34,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_ainfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_ainfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_ainfo_copy(const void *_mesg, void *_dest);
 static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -104,7 +104,8 @@ H5FL_DEFINE_STATIC(H5O_ainfo_t);
  */
 static void *
 H5O_ainfo_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_ainfo_t	*ainfo = NULL;  /* Attribute info */
     unsigned char flags;        /* Flags for encoding attribute info */
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index a8d2a311b2..882912155a 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -26,7 +26,7 @@
 /* PRIVATE PROTOTYPES */
 static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg);
 static void *H5O_attr_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static void *H5O_attr_copy(const void *_mesg, void *_dest);
 static size_t H5O_attr_size(const H5F_t *f, const void *_mesg);
 static herr_t H5O_attr_free(void *mesg);
@@ -121,7 +121,7 @@ H5FL_EXTERN(H5S_extent_t);
 --------------------------------------------------------------------------*/
 static void *
 H5O_attr_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
-    unsigned *ioflags, const uint8_t *p)
+    unsigned *ioflags, size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5A_t		*attr = NULL;
     H5S_extent_t	*extent;	/*extent dimensionality information  */
@@ -187,7 +187,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned H5_ATTR_UNUSED
 
     /* Decode the attribute's datatype */
     if(NULL == (attr->shared->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, open_oh,
-        ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, p)))
+        ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, attr->shared->dt_size, p)))
         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype")
     if(attr->shared->version < H5O_ATTR_VERSION_2)
         p += H5O_ALIGN_OLD(attr->shared->dt_size);
@@ -202,7 +202,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned H5_ATTR_UNUSED
 
     /* Decode attribute's dataspace extent */
     if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, dxpl_id, open_oh,
-        ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, p)) == NULL)
+            ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, attr->shared->ds_size, p)) == NULL)
         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace")
 
     /* Copy the extent information to the dataspace */
diff --git a/src/H5Obogus.c b/src/H5Obogus.c
index 7a058b2452..ba9a8ada34 100644
--- a/src/H5Obogus.c
+++ b/src/H5Obogus.c
@@ -37,7 +37,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_bogus_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_bogus_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static size_t H5O_bogus_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
 static herr_t H5O_bogus_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream,
@@ -110,7 +110,8 @@ const H5O_msg_class_t H5O_MSG_BOGUS_INVALID[1] = {{
  */
 static void *
 H5O_bogus_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_bogus_t *mesg = NULL;
     void *ret_value;            /* Return value */
diff --git a/src/H5Obtreek.c b/src/H5Obtreek.c
index 70aacc7644..6bcdcc3af3 100644
--- a/src/H5Obtreek.c
+++ b/src/H5Obtreek.c
@@ -27,7 +27,7 @@
 #include "H5MMprivate.h"	/* Memory management			*/
 
 static void  *H5O_btreek_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_btreek_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void  *H5O_btreek_copy(const void *_mesg, void *_dest);
 static size_t H5O_btreek_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -78,7 +78,8 @@ const H5O_msg_class_t H5O_MSG_BTREEK[1] = {{
  */
 static void *
 H5O_btreek_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_btreek_t	*mesg;          /* Native message */
     void                *ret_value;     /* Return value */
diff --git a/src/H5Ocache_image.c b/src/H5Ocache_image.c
new file mode 100644
index 0000000000..d2b65bbb8c
--- /dev/null
+++ b/src/H5Ocache_image.c
@@ -0,0 +1,377 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group.                                               *
+ * Copyright by the Board of Trustees of the University of Illinois.         *
+ * All rights reserved.                                                      *
+ *                                                                           *
+ * This file is part of HDF5.  The full HDF5 copyright notice, including     *
+ * terms governing use, modification, and redistribution, is contained in    *
+ * the COPYING file, which can be found at the root of the source code       *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
+ * If you do not have access to either file, you may request a copy from     *
+ * help@hdfgroup.org.                                                        *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created:     H5Ocache_image.c
+ *              June 21, 2015
+ *              John Mainzer
+ *
+ * Purpose:     A message indicating that a metadata cache image block
+ *		of the indicated length exists at the specified offset
+ *		in the HDF5 file.
+ *
+ * 		The mdci_msg only appears in the superblock extension.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "H5Omodule.h"          /* This source code file is part of the H5O module */
+
+
+#include "H5private.h"          /* Generic Functions                     */
+#include "H5Eprivate.h"         /* Error handling                        */
+#include "H5Fprivate.h"		/* Files				*/
+#include "H5FLprivate.h"        /* Free Lists                            */
+#include "H5Opkg.h"             /* Object headers                        */
+#include "H5MFprivate.h"        /* File space management                 */
+
+/* Callbacks for message class */
+static void *H5O__mdci_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
+static herr_t H5O__mdci_encode(H5F_t *f, hbool_t disable_shared, 
+    uint8_t *p, const void *_mesg);
+static void *H5O__mdci_copy(const void *_mesg, void *_dest);
+static size_t H5O__mdci_size(const H5F_t *f, hbool_t disable_shared, 
+    const void *_mesg);
+static herr_t H5O__mdci_free(void *mesg);
+static herr_t H5O__mdci_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
+    void *_mesg);
+static herr_t H5O__mdci_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
+    FILE *stream, int indent, int fwidth);
+
+/* This message derives from H5O message class */
+const H5O_msg_class_t H5O_MSG_MDCI[1] = {{
+    H5O_MDCI_MSG_ID,            /* message id number              */
+    "mdci",                     /* message name for debugging     */
+    sizeof(H5O_mdci_t),         /* native message size            */
+    0,                          /* messages are sharable?         */
+    H5O__mdci_decode,           /* decode message                 */
+    H5O__mdci_encode,           /* encode message                 */
+    H5O__mdci_copy,             /* copy method                    */
+    H5O__mdci_size,             /* size of mdc image message      */
+    NULL,                       /* reset method                   */
+    H5O__mdci_free,             /* free method                    */
+    H5O__mdci_delete,		/* file delete method             */
+    NULL,                       /* link method                    */
+    NULL,                       /* set share method               */
+    NULL,                       /* can share method               */
+    NULL,                       /* pre copy native value to file  */
+    NULL,                       /* copy native value to file      */
+    NULL,                       /* post copy native value to file */
+    NULL,                       /* get creation index             */
+    NULL,                       /* set creation index             */
+    H5O__mdci_debug             /* debugging                      */
+}};
+
+/* Only one version of the metadata cache image message at present */
+#define H5O_MDCI_VERSION_0 	0
+
+/* Declare the free list for H5O_mdci_t's */
+H5FL_DEFINE(H5O_mdci_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_decode
+ *
+ * Purpose:     Decode a metadata cache image  message and return a
+ * 		pointer to a newly allocated H5O_mdci_t struct.
+ *
+ * Return:      Success:        Ptr to new message in native struct.
+ *              Failure:        NULL
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__mdci_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, 
+    H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, 
+    unsigned H5_ATTR_UNUSED *ioflags, size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
+{
+    H5O_mdci_t      *mesg;                  /* Native message        */
+    void            *ret_value = NULL;      /* Return value          */
+
+    FUNC_ENTER_STATIC
+
+    /* Sanity check */
+    HDassert(f);
+    HDassert(p);
+
+    /* Version of message */
+    if(*p++ != H5O_MDCI_VERSION_0)
+        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")
+
+    /* Allocate space for message */
+    if(NULL == (mesg = (H5O_mdci_t *)H5FL_MALLOC(H5O_mdci_t)))
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for metadata cache image message")
+
+    /* Decode */
+    H5F_addr_decode(f, &p, &(mesg->addr));
+    H5F_DECODE_LENGTH(f, p, mesg->size);
+
+    /* Set return value */
+    ret_value = (void *)mesg;
+
+done:
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_encode
+ *
+ * Purpose:     Encode metadata cache image message
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, 
+    uint8_t *p, const void *_mesg)
+{
+    const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg;
+
+    FUNC_ENTER_STATIC_NOERR
+
+    /* Sanity check */
+    HDassert(f);
+    HDassert(p);
+    HDassert(mesg);
+
+    /* encode */
+    *p++ = H5O_MDCI_VERSION_0;
+    H5F_addr_encode(f, &p, mesg->addr);
+    H5F_ENCODE_LENGTH(f, p, mesg->size);
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_copy
+ *
+ * Purpose:     Copies a message from _MESG to _DEST, allocating _DEST if
+ *              necessary.
+ *
+ * Return:      Success:        Ptr to _DEST
+ *              Failure:        NULL
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__mdci_copy(const void *_mesg, void *_dest)
+{
+    const H5O_mdci_t   *mesg = (const H5O_mdci_t *)_mesg;
+    H5O_mdci_t         *dest = (H5O_mdci_t *) _dest;
+    void               *ret_value = NULL;   /* Return value */
+
+    FUNC_ENTER_STATIC
+
+    /* check args */
+    HDassert(mesg);
+    if(!dest && NULL == (dest = H5FL_MALLOC(H5O_mdci_t)))
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+    /* copy */
+    *dest = *mesg;
+
+    /* Set return value */
+    ret_value = dest;
+
+done:
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_mdci__copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_size
+ *
+ * Purpose:     Returns the size of the raw message in bytes not counting
+ *              the message type or size fields, but only the data fields.
+ *              This function doesn't take into account alignment.
+ *
+ * Return:      Success:        Message data size in bytes without alignment.
+ *
+ *              Failure:        zero
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5O__mdci_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, 
+    const void H5_ATTR_UNUSED *_mesg)
+{
+    size_t ret_value = 0;       /* Return value */
+
+    FUNC_ENTER_STATIC_NOERR
+
+    /* Set return value */
+    ret_value = (size_t)( 1 +                   /* Version number           */ 
+                          H5F_SIZEOF_ADDR(f) +  /* addr of metadata cache   */
+                                                /* image block              */
+                          H5F_SIZEOF_SIZE(f) ); /* length of metadata cache */
+                                                /* image block              */
+
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_free
+ *
+ * Purpose:     Free the message
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_free(void *mesg)
+{
+    FUNC_ENTER_STATIC_NOERR
+
+    HDassert(mesg);
+
+    mesg = H5FL_FREE(H5O_mdci_t, mesg);
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_delete
+ *
+ * Purpose:     Free file space referenced by message
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  Quincey Koziol
+ *              Wednesday, March 19, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg)
+{
+    H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg;
+    herr_t ret_value = SUCCEED;   /* Return value */
+
+    FUNC_ENTER_STATIC
+
+    /* check args */
+    HDassert(f);
+    HDassert(open_oh);
+    HDassert(mesg);
+
+    /* Free file space for cache image */
+    if(H5F_addr_defined(mesg->addr)) {
+        /* The space for the cache image block was allocated directly
+         * from the VFD layer at the end of file.  As this was the
+         * last file space allocation before shutdown, the cache image
+         * should still be the last item in the file.
+         *
+         * If the hack to work around the self referential free space
+         * manager issue is in use, file space for the non-empty self
+         * referential free space managers was also allocated from VFD
+         * layer at the end of file.  Since these allocations directly
+         * preceeded the cache image allocation they should be directly
+         * adjacent to the cache image block at the end of file.
+         *
+         * In this case, just call H5MF_tidy_self_referential_fsm_hack().
+         *
+         * That routine will float the self referential free space
+         * managers, and reduce the eoa to its value just prior to
+         * allocation of space for same.  Since the cache image appears
+         * just after the self referential free space managers, this
+         * will release the file space for the cache image as well.
+         *
+         * Note that in this case, there must not have been any file
+         * space allocations / deallocations prior to the free of the
+         * cache image.  Verify this to the extent possible.
+         *
+         * If the hack to work around the persistant self referential
+         * free space manager issue is NOT in use, just call H5MF_xfree()
+         * to release the cache iamge.  In principle, we should be able
+         * to just reduce the EOA to the base address of the cache
+         * image block, as there shouldn't be any file space allocation
+         * before the first metadata cache access.  However, given
+         * time constraints, I don't want to go there now.
+         */
+        if(H5F_FIRST_ALLOC_DEALLOC(f)) {
+            HDassert(HADDR_UNDEF != H5F_EOA_PRE_FSM_FSALLOC(f));
+            HDassert(H5F_addr_ge(mesg->addr, H5F_EOA_PRE_FSM_FSALLOC(f)));
+            if(H5MF_tidy_self_referential_fsm_hack(f, dxpl_id) < 0)
+                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
+        } /* end if */
+        else {
+            if(H5MF_xfree(f, H5FD_MEM_SUPER, dxpl_id, mesg->addr, mesg->size) < 0)
+                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block")
+        } /* end else */
+    } /* end if */
+
+done:
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O__mdci_debug
+ *
+ * Purpose:     Prints debugging info.
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  John Mainzer
+ *              6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_debug(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, 
+    const void *_mesg, FILE * stream, int indent, int fwidth)
+{
+    const H5O_mdci_t   *mdci = (const H5O_mdci_t *) _mesg;
+
+    FUNC_ENTER_STATIC_NOERR
+
+    /* check args */
+    HDassert(f);
+    HDassert(mdci);
+    HDassert(stream);
+    HDassert(indent >= 0);
+    HDassert(fwidth >= 0);
+
+    HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+              "Metadata Cache Image Block address:", mdci->addr);
+
+    HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+              "Metadata Cache Image Block size in bytes:", mdci->size);
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_debug() */
+
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 681f54a748..b91b1814ef 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -36,7 +36,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_cont_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static size_t H5O_cont_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
 static herr_t H5O_cont_free(void *mesg);
@@ -89,7 +89,8 @@ H5FL_DEFINE(H5O_cont_t);
  */
 static void *
 H5O_cont_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_cont_t             *cont = NULL;
     void                   *ret_value;
diff --git a/src/H5Odrvinfo.c b/src/H5Odrvinfo.c
index 6f715f8bd2..fd8ad6b7ef 100644
--- a/src/H5Odrvinfo.c
+++ b/src/H5Odrvinfo.c
@@ -27,7 +27,7 @@
 #include "H5MMprivate.h"	/* Memory management			*/
 
 static void  *H5O_drvinfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_drvinfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void  *H5O_drvinfo_copy(const void *_mesg, void *_dest);
 static size_t H5O_drvinfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -79,7 +79,8 @@ const H5O_msg_class_t H5O_MSG_DRVINFO[1] = {{
  */
 static void *
 H5O_drvinfo_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_drvinfo_t	*mesg;          /* Native message */
     void                *ret_value;     /* Return value */
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 774b07103b..85fbef4020 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -29,7 +29,7 @@
 /* PRIVATE PROTOTYPES */
 static herr_t H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg);
 static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static void *H5O_dtype_copy(const void *_mesg, void *_dest);
 static size_t H5O_dtype_size(const H5F_t *f, const void *_mesg);
 static herr_t H5O_dtype_reset(void *_mesg);
@@ -1093,7 +1093,7 @@ done:
 --------------------------------------------------------------------------*/
 static void *
 H5O_dtype_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
-    unsigned *ioflags/*in,out*/, const uint8_t *p)
+    unsigned *ioflags/*in,out*/, size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5T_t	*dt = NULL;
     void        *ret_value;     /* Return value */
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index 218d2503a5..546eb4fc57 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -28,7 +28,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_efl_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_efl_copy(const void *_mesg, void *_dest);
 static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -88,7 +88,8 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{
  */
 static void *
 H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_efl_t   *mesg = NULL;
     int         version;
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index 721c648b3d..70704c5913 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -32,11 +32,11 @@
 
 
 static void  *H5O_fill_old_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_fill_old_encode(H5F_t *f, uint8_t *p, const void *_mesg);
 static size_t H5O_fill_old_size(const H5F_t *f, const void *_mesg);
 static void  *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg);
 static size_t H5O_fill_new_size(const H5F_t *f, const void *_mesg);
 static void  *H5O_fill_copy(const void *_mesg, void *_dest);
@@ -183,7 +183,8 @@ H5FL_BLK_EXTERN(type_conv);
  */
 static void *
 H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_fill_t	*fill = NULL;
     void	*ret_value;
@@ -297,7 +298,8 @@ done:
  */
 static void *
 H5O_fill_old_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_fill_t *fill = NULL;		/* Decoded fill value message */
     void *ret_value;                    /* Return value */
diff --git a/src/H5Ofsinfo.c b/src/H5Ofsinfo.c
new file mode 100644
index 0000000000..8369ae14ff
--- /dev/null
+++ b/src/H5Ofsinfo.c
@@ -0,0 +1,408 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group.                                               *
+ * Copyright by the Board of Trustees of the University of Illinois.         *
+ * All rights reserved.                                                      *
+ *                                                                           *
+ * This file is part of HDF5.  The full HDF5 copyright notice, including     *
+ * terms governing use, modification, and redistribution, is contained in    *
+ * the COPYING file, which can be found at the root of the source code       *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
+ * If you do not have access to either file, you may request a copy from     *
+ * help@hdfgroup.org.                                                        *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created:             H5Ofsinfo.c
+ *                      Feb 2009
+ *			Vailin Choi
+ *
+ * Purpose:             File space info message.
+ *
+ *-------------------------------------------------------------------------
+ */
+#define H5F_FRIEND              /*suppress error about including H5Fpkg   */
+#include "H5Omodule.h"          /* This source code file is part of the H5O module */
+
+
+#include "H5private.h"		/* Generic Functions	*/
+#include "H5Eprivate.h"		/* Error handling	*/
+#include "H5Fpkg.h"             /* File access          */
+#include "H5FLprivate.h"	/* Free lists          	*/
+#include "H5Opkg.h"             /* Object headers	*/
+
+/* PRIVATE PROTOTYPES */
+static void *H5O_fsinfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned mesg_flags,
+        unsigned *ioflags, size_t p_size, const uint8_t *p);
+static herr_t H5O_fsinfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
+static void *H5O_fsinfo_copy(const void *_mesg, void *_dest);
+static size_t H5O_fsinfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
+static herr_t H5O_fsinfo_free(void *mesg);
+static herr_t H5O_fsinfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
+    FILE * stream, int indent, int fwidth);
+
+/* This message derives from H5O message class */
+const H5O_msg_class_t H5O_MSG_FSINFO[1] = {{
+    H5O_FSINFO_ID,            	/* message id number             	*/
+    "fsinfo",                 	/* message name for debugging    	*/
+    sizeof(H5O_fsinfo_t),     	/* native message size           	*/
+    0,				/* messages are sharable?        	*/
+    H5O_fsinfo_decode,        	/* decode message                	*/
+    H5O_fsinfo_encode,        	/* encode message                	*/
+    H5O_fsinfo_copy,          	/* copy the native value         	*/
+    H5O_fsinfo_size,          	/* size of free-space manager info message */
+    NULL,                   	/* default reset method         	*/
+    H5O_fsinfo_free,	        /* free method				*/
+    NULL,        		/* file delete method			*/
+    NULL,			/* link method				*/
+    NULL,			/* set share method			*/
+    NULL,		    	/* can share method			*/
+    NULL,			/* pre copy native value to file 	*/
+    NULL,			/* copy native value to file    	*/
+    NULL,			/* post copy native value to file	*/
+    NULL,			/* get creation index			*/
+    NULL,			/* set creation index			*/
+    H5O_fsinfo_debug          	/* debug the message            	*/
+}};
+
+/* Current version of free-space manager info information */
+#define H5O_FSINFO_VERSION_0 	0
+#define H5O_FSINFO_VERSION_1 	1
+
+/* Declare a free list to manage the H5O_fsinfo_t struct */
+H5FL_DEFINE_STATIC(H5O_fsinfo_t);
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_decode
+ *
+ * Purpose:     Decode a message and return a pointer to a newly allocated one.
+ *
+ * Return:      Success:        Ptr to new message in native form.
+ *              Failure:        NULL
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O_fsinfo_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
+{
+    H5O_fsinfo_t    *fsinfo = NULL;     /* File space info message */
+    H5F_mem_page_t  ptype;              /* Memory type for iteration */
+    unsigned        vers;               /* message version */
+    void            *ret_value = NULL;  /* Return value */
+
+    FUNC_ENTER_NOAPI_NOINIT
+
+    /* check args */
+    HDassert(f);
+    HDassert(p);
+
+    /* Allocate space for message */
+    if(NULL == (fsinfo = H5FL_CALLOC(H5O_fsinfo_t)))
+	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+    for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
+        fsinfo->fs_addr[ptype - 1] = HADDR_UNDEF;
+
+    /* Version of message */
+    vers = *p++;
+
+    if(vers == H5O_FSINFO_VERSION_0) {
+        H5F_file_space_type_t strategy;     /* Strategy */
+        hsize_t threshold;                  /* Threshold */
+        H5FD_mem_t type;                    /* Memory type for iteration */
+
+        fsinfo->persist = H5F_FREE_SPACE_PERSIST_DEF;
+        fsinfo->threshold = H5F_FREE_SPACE_THRESHOLD_DEF;
+        fsinfo->page_size = H5F_FILE_SPACE_PAGE_SIZE_DEF;
+        fsinfo->pgend_meta_thres = H5F_FILE_SPACE_PGEND_META_THRES;
+        fsinfo->eoa_pre_fsm_fsalloc = HADDR_UNDEF;
+
+        strategy = (H5F_file_space_type_t)*p++; /* File space strategy */
+        H5F_DECODE_LENGTH(f, p, threshold);     /* Free-space section threshold */
+
+        /* Map version 0 (deprecated) to version 1 message */
+        switch(strategy) {
+
+            case H5F_FILE_SPACE_ALL_PERSIST:
+                fsinfo->strategy = H5F_FSPACE_STRATEGY_FSM_AGGR;
+                fsinfo->persist = TRUE;
+                fsinfo->threshold = threshold;
+                if(HADDR_UNDEF == (fsinfo->eoa_pre_fsm_fsalloc = H5F_get_eoa(f, H5FD_MEM_DEFAULT)) )
+                    HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file size")
+                for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+                    H5F_addr_decode(f, &p, &(fsinfo->fs_addr[type-1]));
+                break;
+
+            case H5F_FILE_SPACE_ALL:
+                fsinfo->strategy = H5F_FSPACE_STRATEGY_FSM_AGGR;
+                fsinfo->threshold = threshold;
+                break;
+
+            case H5F_FILE_SPACE_AGGR_VFD:
+                fsinfo->strategy = H5F_FSPACE_STRATEGY_AGGR;
+                break;
+
+            case H5F_FILE_SPACE_VFD:
+                fsinfo->strategy = H5F_FSPACE_STRATEGY_NONE;
+                break;
+
+            case H5F_FILE_SPACE_NTYPES:
+            case H5F_FILE_SPACE_DEFAULT:
+            default:
+                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file space strategy")
+        } /* end switch */
+
+        fsinfo->mapped = TRUE;
+       
+    } else {
+        HDassert(vers == H5O_FSINFO_VERSION_1);
+
+        fsinfo->strategy = (H5F_fspace_strategy_t)*p++; /* File space strategy */
+        fsinfo->persist = *p++;                         /* Free-space persist or not */
+        H5F_DECODE_LENGTH(f, p, fsinfo->threshold);     /* Free-space section threshold */
+
+        H5F_DECODE_LENGTH(f, p, fsinfo->page_size); /* File space page size */
+        UINT16DECODE(p, fsinfo->pgend_meta_thres);  /* Page end metdata threshold */
+        H5F_addr_decode(f, &p, &(fsinfo->eoa_pre_fsm_fsalloc)); /* EOA before free-space header and section info */
+
+        /* Decode addresses of free space managers, if persisting */
+        if(fsinfo->persist) {
+            for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
+                H5F_addr_decode(f, &p, &(fsinfo->fs_addr[ptype - 1]));
+        } /* end if */
+
+        fsinfo->mapped = FALSE;
+    }
+
+    /* Set return value */
+    ret_value = fsinfo;
+
+done:
+    if(ret_value == NULL && fsinfo != NULL)
+        fsinfo = H5FL_FREE(H5O_fsinfo_t, fsinfo);
+
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_encode
+ *
+ * Purpose:     Encodes a message.
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_fsinfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg)
+{
+    const H5O_fsinfo_t  *fsinfo = (const H5O_fsinfo_t *)_mesg;
+    H5F_mem_page_t 	ptype;  /* Memory type for iteration */
+
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    /* check args */
+    HDassert(f);
+    HDassert(p);
+    HDassert(fsinfo);
+
+    *p++ = H5O_FSINFO_VERSION_1;	/* message version */
+    *p++ = fsinfo->strategy;	    /* File space strategy */
+    *p++ = (unsigned char)fsinfo->persist;	/* Free-space persist or not */
+    H5F_ENCODE_LENGTH(f, p, fsinfo->threshold); /* Free-space section size threshold */
+
+    H5F_ENCODE_LENGTH(f, p, fsinfo->page_size);	/* File space page size */
+    UINT16ENCODE(p, fsinfo->pgend_meta_thres);	/* Page end metadata threshold */
+    H5F_addr_encode(f, &p, fsinfo->eoa_pre_fsm_fsalloc);    /* EOA before free-space header and section info */
+
+    /* Store addresses of free-space managers, if persisting */
+    if(fsinfo->persist) {
+        /* Addresses of free-space managers */
+        for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
+            H5F_addr_encode(f, &p, fsinfo->fs_addr[ptype - 1]);
+    } /* end if */
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_fsinfo_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_copy
+ *
+ * Purpose:     Copies a message from _MESG to _DEST, allocating _DEST if
+ *              necessary.
+ *
+ * Return:      Success:        Ptr to _DEST
+ *              Failure:        NULL
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O_fsinfo_copy(const void *_mesg, void *_dest)
+{
+    const H5O_fsinfo_t  *fsinfo = (const H5O_fsinfo_t *)_mesg;
+    H5O_fsinfo_t        *dest = (H5O_fsinfo_t *) _dest;
+    void                *ret_value = NULL;      /* Return value */
+
+    FUNC_ENTER_NOAPI_NOINIT
+
+    /* check args */
+    HDassert(fsinfo);
+    if(!dest && NULL == (dest = H5FL_CALLOC(H5O_fsinfo_t)))
+	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+    /* copy */
+    *dest = *fsinfo;
+
+    /* Set return value */
+    ret_value = dest;
+
+done:
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_size
+ *
+ * Purpose:     Returns the size of the raw message in bytes not counting
+ *              the message type or size fields, but only the data fields.
+ *              This function doesn't take into account alignment.
+ *
+ * Return:      Success:        Message data size in bytes without alignment.
+ *              Failure:        zero
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5O_fsinfo_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void *_mesg)
+{
+    const H5O_fsinfo_t   *fsinfo = (const H5O_fsinfo_t *)_mesg;
+    size_t ret_value = 0;       /* Return value */
+
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    ret_value = 3                       /* Version, strategy & persist */
+		+ (size_t)H5F_SIZEOF_SIZE(f)    /* Free-space section threshold */
+		+ (size_t)H5F_SIZEOF_SIZE(f)    /* File space page size */
+		+ 2                             /* Page end meta threshold */
+		+ (size_t)H5F_SIZEOF_ADDR(f);
+    
+    /* Free-space manager addresses */
+    if(fsinfo->persist)
+        ret_value += (H5F_MEM_PAGE_NTYPES - 1) * (size_t)H5F_SIZEOF_ADDR(f);
+
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_free
+ *
+ * Purpose:     Free's the message
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_fsinfo_free(void *mesg)
+{
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    HDassert(mesg);
+
+    mesg = H5FL_FREE(H5O_fsinfo_t, mesg);
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_fsinfo_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5O_fsinfo_debug
+ *
+ * Purpose:     Prints debugging info for a message.
+ *
+ * Return:      Non-negative on success/Negative on failure
+ *
+ * Programmer:  Vailin Choi; Feb 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_fsinfo_debug(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, const void *_mesg, FILE * stream,
+	       int indent, int fwidth)
+{
+    const H5O_fsinfo_t	*fsinfo = (const H5O_fsinfo_t *) _mesg;
+    H5F_mem_page_t  ptype;      /* Free-space types for iteration */
+
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    /* check args */
+    HDassert(f);
+    HDassert(fsinfo);
+    HDassert(stream);
+    HDassert(indent >= 0);
+    HDassert(fwidth >= 0);
+
+    HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "File space strategy:");
+    switch(fsinfo->strategy) {
+        case H5F_FSPACE_STRATEGY_FSM_AGGR:
+            HDfprintf(stream, "%s\n", "H5F_FSPACE_STRATEGY_FSM_AGGR");
+            break;
+
+        case H5F_FSPACE_STRATEGY_PAGE:
+            HDfprintf(stream, "%s\n", "H5F_FSPACE_STRATEGY_PAGE");
+            break;
+
+        case H5F_FSPACE_STRATEGY_AGGR:
+            HDfprintf(stream, "%s\n", "H5F_FSPACE_STRATEGY_AGGR");
+            break;
+
+        case H5F_FSPACE_STRATEGY_NONE:
+            HDfprintf(stream, "%s\n", "H5F_FSPACE_STRATEGY_NONE");
+            break;
+
+        case H5F_FSPACE_STRATEGY_NTYPES:
+        default:
+            HDfprintf(stream, "%s\n", "unknown");
+    } /* end switch */
+
+    HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
+              "Free-space persist:", fsinfo->persist);
+
+    HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+              "Free-space section threshold:", fsinfo->threshold);
+
+    HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+              "File space page size:", fsinfo->page_size);
+
+    HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+              "Page end metadata threshold:", fsinfo->pgend_meta_thres);
+
+    HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+              "eoa_pre_fsm_fsalloc:", fsinfo->eoa_pre_fsm_fsalloc);
+
+    if(fsinfo->persist) {
+        for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
+            HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+                "Free space manager address:", fsinfo->fs_addr[ptype-1]);
+    } /* end if */
+
+    FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_fsinfo_debug() */
+
diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c
index d8be51fa04..8ba1f71d9f 100644
--- a/src/H5Oginfo.c
+++ b/src/H5Oginfo.c
@@ -32,7 +32,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_ginfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_ginfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_ginfo_copy(const void *_mesg, void *_dest);
 static size_t H5O_ginfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -94,7 +94,8 @@ H5FL_DEFINE_STATIC(H5O_ginfo_t);
  */
 static void *
 H5O_ginfo_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_ginfo_t         *ginfo = NULL;  /* Pointer to group information message */
     unsigned char       flags;          /* Flags for encoding group info */
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index 3bbee129e0..5c5ad42730 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -35,7 +35,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_layout_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_layout_copy(const void *_mesg, void *_dest);
 static size_t H5O_layout_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -95,7 +95,8 @@ H5FL_DEFINE(H5O_layout_t);
  */
 static void *
 H5O_layout_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_layout_t           *mesg = NULL;
     unsigned               u;
diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c
index 03e545f260..a612ae5e2b 100644
--- a/src/H5Olinfo.c
+++ b/src/H5Olinfo.c
@@ -36,7 +36,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_linfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_linfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_linfo_copy(const void *_mesg, void *_dest);
 static size_t H5O_linfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -113,7 +113,8 @@ H5FL_DEFINE_STATIC(H5O_linfo_t);
  */
 static void *
 H5O_linfo_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_linfo_t	*linfo = NULL;  /* Link info */
     unsigned char index_flags;  /* Flags for encoding link index info */
diff --git a/src/H5Olink.c b/src/H5Olink.c
index 1b57f22529..c0dd1d8c4b 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -38,7 +38,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_link_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_link_copy(const void *_mesg, void *_dest);
 static size_t H5O_link_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -117,7 +117,8 @@ H5FL_DEFINE_STATIC(H5O_link_t);
  */
 static void *
 H5O_link_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_link_t          *lnk = NULL;    /* Pointer to link message */
     size_t              len = 0;        /* Length of a string in the message */
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index bbcf5a6ea7..98517a34ed 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -1821,7 +1821,7 @@ done:
  */
 void *
 H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
-    const unsigned char *buf)
+    size_t buf_size, const unsigned char *buf)
 {
     const H5O_msg_class_t   *type;      /* Actual H5O class type for the ID */
     void *ret_value;                    /* Return value */
@@ -1836,7 +1836,7 @@ H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
     HDassert(type);
 
     /* decode */
-    if((ret_value = (type->decode)(f, dxpl_id, open_oh, 0, &ioflags, buf)) == NULL)
+    if((ret_value = (type->decode)(f, dxpl_id, open_oh, 0, &ioflags, buf_size, buf)) == NULL)
         HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message")
 
 done:
diff --git a/src/H5Omtime.c b/src/H5Omtime.c
index 46dd499250..e4db09bad3 100644
--- a/src/H5Omtime.c
+++ b/src/H5Omtime.c
@@ -27,12 +27,12 @@
 
 
 static void *H5O_mtime_new_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_mtime_new_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static size_t H5O_mtime_new_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
 
 static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_mtime_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_mtime_copy(const void *_mesg, void *_dest);
 static size_t H5O_mtime_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -118,7 +118,8 @@ H5FL_DEFINE(time_t);
  */
 static void *
 H5O_mtime_new_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     time_t	*mesg;
     uint32_t    tmp_time;       /* Temporary copy of the time */
@@ -171,7 +172,8 @@ done:
  */
 static void *
 H5O_mtime_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     time_t	*mesg, the_time;
     int	i;
diff --git a/src/H5Oname.c b/src/H5Oname.c
index 007e20f9a6..5248168c30 100644
--- a/src/H5Oname.c
+++ b/src/H5Oname.c
@@ -32,7 +32,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_name_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_name_copy(const void *_mesg, void *_dest);
 static size_t H5O_name_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -83,7 +83,8 @@ const H5O_msg_class_t H5O_MSG_NAME[1] = {{
  */
 static void *
 H5O_name_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_name_t          *mesg;
     void                *ret_value;     /* Return value */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index cd585beefd..f4b80147b8 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -186,7 +186,7 @@
                                                                               \
         /* Decode the message */                                              \
         HDassert(msg_type->decode);                                           \
-        if(NULL == ((MSG)->native = (msg_type->decode)((F), (DXPL), (OH), (MSG)->flags, &ioflags, (MSG)->raw))) \
+        if(NULL == ((MSG)->native = (msg_type->decode)((F), (DXPL), (OH), (MSG)->flags, &ioflags, (MSG)->raw_size, (MSG)->raw))) \
             HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, ERR, "unable to decode message") \
                                                                               \
         /* Mark the message dirty if it was changed by decoding */            \
@@ -222,7 +222,7 @@ struct H5O_msg_class_t {
     const char	*name;				/*for debugging             */
     size_t	native_size;			/*size of native message    */
     unsigned    share_flags;			/* Message sharing settings */
-    void	*(*decode)(H5F_t *, hid_t, H5O_t *, unsigned, unsigned *, const uint8_t *);
+    void	*(*decode)(H5F_t *, hid_t, H5O_t *, unsigned, unsigned *, size_t, const uint8_t *);
     herr_t	(*encode)(H5F_t *, hbool_t, uint8_t *, const void *);
     void	*(*copy)(const void *, void *);	/*copy native value         */
     size_t	(*raw_size)(const H5F_t *, hbool_t, const void *);/*sizeof encoded message	*/
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 42fb72c9cb..0cd791213c 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -33,7 +33,7 @@
 /* PRIVATE PROTOTYPES */
 static herr_t H5O_pline_encode(H5F_t *f, uint8_t *p, const void *mesg);
 static void *H5O_pline_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static void *H5O_pline_copy(const void *_mesg, void *_dest);
 static size_t H5O_pline_size(const H5F_t *f, const void *_mesg);
 static herr_t H5O_pline_reset(void *_mesg);
@@ -108,13 +108,15 @@ H5FL_DEFINE(H5O_pline_t);
  */
 static void *
 H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t p_size, const uint8_t *p)
 {
     H5O_pline_t		*pline = NULL;          /* Pipeline message */
     H5Z_filter_info_t   *filter;                /* Filter to decode */
     size_t		name_length;            /* Length of filter name */
     size_t		i;                      /* Local index variable */
-    void		*ret_value;             /* Return value */
+    const uint8_t *p_end = p + p_size - 1;  /* End of the p buffer */
+    void		*ret_value = NULL;      /* Return value */
 
     FUNC_ENTER_NOAPI_NOINIT
 
@@ -123,12 +125,12 @@ H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5
 
     /* Allocate space for I/O pipeline message */
     if(NULL == (pline = H5FL_CALLOC(H5O_pline_t)))
-	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
 
     /* Version */
     pline->version = *p++;
     if(pline->version < H5O_PLINE_VERSION_1 || pline->version > H5O_PLINE_VERSION_LATEST)
-	HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message")
+        HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message")
 
     /* Number of filters */
     pline->nused = *p++;
@@ -142,12 +144,12 @@ H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5
     /* Allocate array for filters */
     pline->nalloc = pline->nused;
     if(NULL == (pline->filter = (H5Z_filter_info_t *)H5MM_calloc(pline->nalloc * sizeof(pline->filter[0]))))
-	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
 
     /* Decode filters */
     for(i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) {
         /* Filter ID */
-	UINT16DECODE(p, filter->id);
+        UINT16DECODE(p, filter->id);
 
         /* Length of filter name */
         if(pline->version > H5O_PLINE_VERSION_1 && filter->id < H5Z_FILTER_RESERVED)
@@ -159,18 +161,18 @@ H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5
         } /* end if */
 
         /* Filter flags */
-	UINT16DECODE(p, filter->flags);
+        UINT16DECODE(p, filter->flags);
 
         /* Number of filter parameters ("client data elements") */
-	UINT16DECODE(p, filter->cd_nelmts);
+        UINT16DECODE(p, filter->cd_nelmts);
 
         /* Filter name, if there is one */
-	if(name_length) {
+        if(name_length) {
             size_t actual_name_length;          /* Actual length of name */
 
             /* Determine actual name length (without padding, but with null terminator) */
-	    actual_name_length = HDstrlen((const char *)p) + 1;
-	    HDassert(actual_name_length <= name_length);
+            actual_name_length = HDstrlen((const char *)p) + 1;
+            HDassert(actual_name_length <= name_length);
 
             /* Allocate space for the filter name, or use the internal buffer */
             if(actual_name_length > H5Z_COMMON_NAME_LEN) {
@@ -181,12 +183,12 @@ H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5
             else
                 filter->name = filter->_name;
 
-	    HDstrncpy(filter->name, (const char *)p, actual_name_length);
-	    p += name_length;
-	} /* end if */
+            HDstrncpy(filter->name, (const char *)p, actual_name_length);
+            p += name_length;
+        } /* end if */
 
         /* Filter parameters */
-	if(filter->cd_nelmts) {
+        if(filter->cd_nelmts) {
             size_t	j;              /* Local index variable */
 
             /* Allocate space for the client data elements, or use the internal buffer */
@@ -198,15 +200,20 @@ H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5
             else
                 filter->cd_values = filter->_cd_values;
 
-	    /*
-	     * Read the client data values and the padding
-	     */
-	    for(j = 0; j < filter->cd_nelmts; j++)
-		UINT32DECODE(p, filter->cd_values[j]);
+            /*
+             * Read the client data values and the padding
+             */
+            for (j = 0; j < filter->cd_nelmts; j++) {
+                if (p + 4 - 1 <= p_end)
+                    UINT32DECODE(p, filter->cd_values[j])
+                else
+                    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "ran off the end of the buffer: current p = %p, p_size = %zu, p_end = %p", p, p_size, p_end)
+            }
+
             if(pline->version == H5O_PLINE_VERSION_1)
                 if(filter->cd_nelmts % 2)
                     p += 4; /*padding*/
-	} /* end if */
+        } /* end if */
     } /* end for */
 
     /* Set return value */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index ca0fc8e633..1f51705243 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -710,7 +710,7 @@ H5_DLL herr_t H5O_msg_get_crt_index(unsigned type_id, const void *mesg,
 H5_DLL herr_t H5O_msg_encode(H5F_t *f, unsigned type_id, hbool_t disable_shared,
     unsigned char *buf, const void *obj);
 H5_DLL void* H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned type_id, const unsigned char *buf);
+    unsigned type_id, size_t buf_size, const unsigned char *buf);
 H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
     unsigned type_id, void *mesg);
 H5_DLL int H5O_msg_get_chunkno(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
diff --git a/src/H5Orefcount.c b/src/H5Orefcount.c
index 22b1a02835..78ff791729 100644
--- a/src/H5Orefcount.c
+++ b/src/H5Orefcount.c
@@ -32,7 +32,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_refcount_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_refcount_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_refcount_copy(const void *_mesg, void *_dest);
 static size_t H5O_refcount_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -89,7 +89,8 @@ H5FL_DEFINE_STATIC(H5O_refcount_t);
  */
 static void *
 H5O_refcount_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_refcount_t *refcount = NULL;  /* Reference count */
     void        *ret_value;     /* Return value */
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index 557a44bb3c..627ea190a3 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -26,7 +26,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
 static void *H5O_sdspace_copy(const void *_mesg, void *_dest);
 static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg);
@@ -110,7 +110,8 @@ H5FL_ARR_EXTERN(hsize_t);
 --------------------------------------------------------------------------*/
 static void *
 H5O_sdspace_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5S_extent_t	*sdim = NULL;/* New extent dimensionality structure */
     void		*ret_value;
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index 0d692f9489..2475dd5137 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -156,7 +156,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned *ioflags,
             HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "can't read message from fractal heap.")
 
         /* Decode the message */
-        if(NULL == (ret_value = (type->decode)(f, dxpl_id, open_oh, 0, ioflags, mesg_ptr)))
+        if(NULL == (ret_value = (type->decode)(f, dxpl_id, open_oh, 0, ioflags, mesg_size, mesg_ptr)))
             HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
     } /* end if */
     else {
diff --git a/src/H5Oshared.h b/src/H5Oshared.h
index f71f5f6f36..e60d7ba37b 100644
--- a/src/H5Oshared.h
+++ b/src/H5Oshared.h
@@ -47,7 +47,7 @@
  */
 static H5_INLINE void *
 H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned mesg_flags,
-    unsigned *ioflags, const uint8_t *p)
+    unsigned *ioflags, size_t p_size, const uint8_t *p)
 {
     void *ret_value;            /* Return value */
 
@@ -67,7 +67,7 @@ H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned mesg_flags,
     if(mesg_flags & H5O_MSG_FLAG_SHARED) {
         /* Retrieve native message info indirectly through shared message */
         if(NULL == (ret_value = H5O_shared_decode(f, dxpl_id, open_oh, ioflags, p, H5O_SHARED_TYPE)))
-	    HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message")
+            HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message")
 
         /* We currently do not support automatically fixing shared messages */
 #ifdef H5_STRICT_FORMAT_CHECKS
@@ -79,8 +79,8 @@ H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned mesg_flags,
     } /* end if */
     else {
         /* Decode native message directly */
-        if(NULL == (ret_value = H5O_SHARED_DECODE_REAL(f, dxpl_id, open_oh, mesg_flags, ioflags, p)))
-	    HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode native message")
+        if(NULL == (ret_value = H5O_SHARED_DECODE_REAL(f, dxpl_id, open_oh, mesg_flags, ioflags, p_size, p)))
+            HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode native message")
     } /* end else */
 
 done:
diff --git a/src/H5Oshmesg.c b/src/H5Oshmesg.c
index 536f67e8be..489114aee8 100644
--- a/src/H5Oshmesg.c
+++ b/src/H5Oshmesg.c
@@ -27,7 +27,7 @@
 #include "H5MMprivate.h"	/* Memory management			*/
 
 static void  *H5O_shmesg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_shmesg_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void  *H5O_shmesg_copy(const void *_mesg, void *_dest);
 static size_t H5O_shmesg_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -75,7 +75,8 @@ const H5O_msg_class_t H5O_MSG_SHMESG[1] = {{
  */
 static void *
 H5O_shmesg_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_shmesg_table_t	*mesg;          /* Native message */
     void                *ret_value;     /* Return value */
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 928307e580..cf8c96a6ad 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -35,7 +35,7 @@
 
 /* PRIVATE PROTOTYPES */
 static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
-    unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+    unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
 static herr_t H5O_stab_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
 static void *H5O_stab_copy(const void *_mesg, void *_dest);
 static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -96,7 +96,8 @@ H5FL_DEFINE_STATIC(H5O_stab_t);
  */
 static void *
 H5O_stab_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
-    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+    unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
+    size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
 {
     H5O_stab_t          *stab = NULL;
     void                *ret_value;     /* Return value */
diff --git a/src/H5S.c b/src/H5S.c
index d03d5235c6..50bee52151 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -1644,7 +1644,7 @@ H5S_decode(const unsigned char *buf)
 
     /* Decode the extent part of dataspace */
     /* (pass mostly bogus file pointer and bogus DXPL) */
-    if((extent = (H5S_extent_t *)H5O_msg_decode(f, H5P_DEFAULT, NULL, H5O_SDSPACE_ID, buf))==NULL)
+    if((extent = (H5S_extent_t *)H5O_msg_decode(f, H5P_DEFAULT, NULL, H5O_SDSPACE_ID, extent_size, buf))==NULL)
 	HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode object")
     buf += extent_size;
 
diff --git a/src/H5SM.c b/src/H5SM.c
index 080eb7c54e..b549b593f2 100644
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -69,7 +69,7 @@ static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
 static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed);
 static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
     H5SM_index_header_t *header, const H5O_shared_t * mesg,
-    unsigned *cache_flags, void ** /*out*/ encoded_mesg);
+    unsigned *cache_flags, size_t * /*out*/ mesg_size, void ** /*out*/ encoded_mesg);
 static herr_t H5SM_type_to_flag(unsigned type_id, unsigned *type_flag);
 static herr_t H5SM_read_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
     unsigned *oh_modified, void *_udata);
@@ -1518,6 +1518,7 @@ H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg)
     unsigned              cache_flags = H5AC__NO_FLAGS_SET;
     H5SM_table_cache_ud_t cache_udata;      /* User-data for callback */
     ssize_t               index_num;
+    size_t                mesg_size = 0;
     void                 *mesg_buf = NULL;
     void                 *native_mesg = NULL;
     unsigned              type_id;              /* Message type ID to operate on */
@@ -1547,8 +1548,8 @@ H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg)
      * zero and any file space it uses needs to be freed.  mesg_buf holds the
      * serialized form of the message.
      */
-    if(H5SM_delete_from_index(f, dxpl_id, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_buf) < 0)
-	HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
+    if(H5SM_delete_from_index(f, dxpl_id, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_size, &mesg_buf) < 0)
+        HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
 
     /* Release the master SOHM table */
     if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
@@ -1560,7 +1561,7 @@ H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg)
      * master table needs to be unprotected when we do this.
      */
     if(mesg_buf) {
-        if(NULL == (native_mesg = H5O_msg_decode(f, dxpl_id, open_oh, type_id, (const unsigned char *)mesg_buf)))
+        if(NULL == (native_mesg = H5O_msg_decode(f, dxpl_id, open_oh, type_id, mesg_size, (const unsigned char *)mesg_buf)))
             HGOTO_ERROR(H5E_SOHM, H5E_CANTDECODE, FAIL, "can't decode shared message.")
 
         if(H5O_msg_delete(f, dxpl_id, open_oh, type_id, native_mesg) < 0)
@@ -1747,7 +1748,7 @@ H5SM_decr_ref(void *record, void *op_data, hbool_t *changed)
 static herr_t
 H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
     H5SM_index_header_t *header, const H5O_shared_t *mesg,
-    unsigned *cache_flags, void ** /*out*/ encoded_mesg)
+    unsigned *cache_flags, size_t * /*out*/ mesg_size, void ** /*out*/ encoded_mesg)
 {
     H5SM_list_t     *list = NULL;
     H5SM_mesg_key_t key;
@@ -1879,6 +1880,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
 
         /* Return the message's encoding so anything it references can be freed */
         *encoded_mesg = encoding_buf;
+        *mesg_size = buf_size;
 
         /* If there are no messages left in the index, delete it */
         if(header->num_messages == 0) {
@@ -1920,8 +1922,10 @@ done:
     /* Free the message encoding, if we're not returning it in encoded_mesg
      * or if there's been an error.
      */
-    if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0))
+    if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0)) {
         encoding_buf = H5MM_xfree(encoding_buf);
+        *mesg_size = 0;
+    }
 
     FUNC_LEAVE_NOAPI(ret_value)
 } /* end H5SM_delete_from_index() */
diff --git a/src/H5T.c b/src/H5T.c
index d705b99d33..9eeb7db193 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -2801,8 +2801,13 @@ H5Tdecode(const void *buf)
     if(buf == NULL)
         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer")
 
-    /* Create datatype by decoding buffer */
-    if(NULL == (dt = H5T_decode((const unsigned char *)buf)))
+    /* Create datatype by decoding buffer
+     * There is no way to get the size of the buffer, so we pass in
+     * SIZE_MAX and assume the caller knows what they are doing.
+     * Really fixing this will require an H5Tdecode2() call that
+     * takes a size parameter.
+     */
+    if(NULL == (dt = H5T_decode(SIZE_MAX, (const unsigned char *)buf)))
         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "can't decode object")
 
     /* Register the type and return the ID */
@@ -2891,7 +2896,7 @@ done:
  *-------------------------------------------------------------------------
  */
 static H5T_t *
-H5T_decode(const unsigned char *buf)
+H5T_decode(size_t buf_size, const unsigned char *buf)
 {
     H5F_t *f = NULL;            /* Fake file structure*/
     H5T_t *ret_value = NULL;    /* Return value */
@@ -2911,7 +2916,7 @@ H5T_decode(const unsigned char *buf)
         HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, NULL, "unknown version of encoded datatype")
 
     /* Decode the serialized datatype message */
-    if(NULL == (ret_value = (H5T_t *)H5O_msg_decode(f, H5AC_ind_dxpl_id, NULL, H5O_DTYPE_ID, buf)))
+    if(NULL == (ret_value = (H5T_t *)H5O_msg_decode(f, H5AC_noio_dxpl_id, NULL, H5O_DTYPE_ID, buf_size, buf)))
         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object")
 
     /* Mark datatype as being in memory now */
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index 81af0567d4..f5191416ad 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -112,6 +112,8 @@ H5_DLL H5T_class_t H5T_get_class(const H5T_t *dt, htri_t internal);
 H5_DLL htri_t H5T_detect_class(const H5T_t *dt, H5T_class_t cls, hbool_t from_api);
 H5_DLL size_t H5T_get_size(const H5T_t *dt);
 H5_DLL int    H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset);
+H5_DLL herr_t H5T_encode(H5T_t *obj, unsigned char *buf, size_t *nalloc);
+H5_DLL H5T_t *H5T_decode(size_t buf_size, const unsigned char *buf);
 H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE * stream);
 H5_DLL struct H5O_loc_t *H5T_oloc(H5T_t *dt);
 H5_DLL H5G_name_t *H5T_nameof(H5T_t *dt);
-- 
2.23.0

