diff options
-rw-r--r-- | src/H5D.c | 8 | ||||
-rw-r--r-- | src/H5O.c | 120 | ||||
-rw-r--r-- | src/H5Obogus.c | 222 | ||||
-rw-r--r-- | src/H5Oprivate.h | 20 | ||||
-rw-r--r-- | src/Makefile.in | 16 | ||||
-rw-r--r-- | test/ohdr.c | 31 | ||||
-rw-r--r-- | test/tbogus.h5 | bin | 0 -> 2052 bytes |
7 files changed, 406 insertions, 11 deletions
@@ -1671,6 +1671,14 @@ H5D_update_entry_info(H5F_t *file, H5D_t *dset, H5P_genplist_t *plist) if (H5D_COMPACT != layout->type && H5O_append(file, oh, H5O_LAYOUT, 0, layout) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout"); +#ifdef H5O_ENABLE_BOGUS + /* + * Add a "bogus" message. + */ + if (H5O_bogus_oh(file, oh))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to update 'bogus' message"); +#endif /* H5O_ENABLE_BOGUS */ + /* Add a modification time message. */ if (H5O_touch_oh(file, oh, TRUE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message"); @@ -67,7 +67,11 @@ static const H5O_class_t *const message_type_g[] = { NULL, /*0x0006 Data storage -- compact object */ H5O_EFL, /*0x0007 Data storage -- external data files */ H5O_LAYOUT, /*0x0008 Data Layout */ - NULL, /*0x0009 Not assigned */ +#ifdef H5O_ENABLE_BOGUS + H5O_BOGUS, /*0x0009 "Bogus" */ +#else /* H5O_ENABLE_BOGUS */ + NULL, /*0x0009 "Bogus" */ +#endif /* H5O_ENABLE_BOGUS */ NULL, /*0x000A Not assigned */ H5O_PLINE, /*0x000B Data storage -- filter pipeline */ H5O_ATTR, /*0x000C Attribute list */ @@ -502,10 +506,15 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1, flags = *p++; p += 3; /*reserved*/ - if (id >= NELMTS(message_type_g) || NULL == message_type_g[id]) - HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "corrupt object header"); + /* Try to detect invalidly formatted object header messages */ if (p + mesg_size > oh->chunk[chunkno].image + chunk_size) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header"); + + /* Skip header messages we don't know about */ + /* (Usually from future versions of the library */ + if (id >= NELMTS(message_type_g) || NULL == message_type_g[id]) + continue; + if (H5O_NULL_ID == id && oh->nmesgs > 0 && H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id && oh->mesg[oh->nmesgs - 1].chunkno == chunkno) { @@ -1719,6 +1728,111 @@ done: FUNC_LEAVE_NOAPI(ret_value); } +#ifdef H5O_ENABLE_BOGUS + +/*------------------------------------------------------------------------- + * Function: H5O_bogus_oh + * + * Purpose: Create a "bogus" message unless one already exists. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * <koziol@ncsa.uiuc.edu> + * Tuesday, January 21, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_bogus_oh(H5F_t *f, H5O_t *oh) +{ + int idx; + size_t size; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER(H5O_bogus_oh, FAIL); + + assert(f); + assert(oh); + + /* Look for existing message */ + for (idx=0; idx<oh->nmesgs; idx++) + if (H5O_BOGUS==oh->mesg[idx].type) + break; + + /* Create a new message */ + if (idx==oh->nmesgs) { + size = (H5O_BOGUS->raw_size)(f, NULL); + if ((idx=H5O_alloc(f, oh, H5O_BOGUS, size))<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for 'bogus' message"); + + /* Allocate the native message in memory */ + if (NULL==(oh->mesg[idx].native = H5MM_malloc(sizeof(H5O_bogus_t)))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for 'bogus' message"); + + /* Update the native part */ + ((H5O_bogus_t *)(oh->mesg[idx].native))->u = H5O_BOGUS_VALUE; + + /* Mark the message and object header as dirty */ + oh->mesg[idx].dirty = TRUE; + oh->dirty = TRUE; + } /* end if */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_bogus_oh() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_bogus + * + * Purpose: Create a "bogus" message in an object. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * <koziol@ncsa.uiuc.edu> + * Tuesday, January 21, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_bogus(H5G_entry_t *ent) +{ + H5O_t *oh = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5O_bogus, FAIL); + + /* check args */ + assert(ent); + assert(ent->file); + assert(H5F_addr_defined(ent->header)); + + /* Verify write access to the file */ + if (0==(ent->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file"); + + /* Get the object header */ + if (NULL==(oh=H5AC_protect(ent->file, H5AC_OHDR, ent->header, NULL, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + + /* Create the "bogus" message */ + if (H5O_bogus_oh(ent->file, oh)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object 'bogus' message"); + +done: + if (oh && H5AC_unprotect(ent->file, H5AC_OHDR, ent->header, oh)<0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + + FUNC_LEAVE(ret_value); +} /* end H5O_bogus() */ +#endif /* H5O_ENABLE_BOGUS */ + /*------------------------------------------------------------------------- * Function: H5O_remove diff --git a/src/H5Obogus.c b/src/H5Obogus.c new file mode 100644 index 0000000..b25e006 --- /dev/null +++ b/src/H5Obogus.c @@ -0,0 +1,222 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Obogus.c + * Jan 21 2003 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: "bogus" message. This message is guaranteed to never + * be found in a valid HDF5 file and is only used to + * generate a test file which verifies the library's + * correct operation when parsing unknown object header + * messages. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include "H5private.h" +#include "H5Eprivate.h" +#include "H5MMprivate.h" +#include "H5Oprivate.h" + +#ifdef H5O_ENABLE_BOGUS +#define PABLO_MASK H5O_bogus_mask + +/* PRIVATE PROTOTYPES */ +static void *H5O_bogus_decode(H5F_t *f, const uint8_t *p, H5O_shared_t *sh); +static herr_t H5O_bogus_encode(H5F_t *f, uint8_t *p, const void *_mesg); +static size_t H5O_bogus_size(H5F_t *f, const void *_mesg); +static herr_t H5O_bogus_debug(H5F_t *f, const void *_mesg, FILE * stream, + int indent, int fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_BOGUS[1] = {{ + H5O_BOGUS_ID, /*message id number */ + "bogus", /*message name for debugging */ + 0, /*native message size */ + H5O_bogus_decode, /*decode message */ + H5O_bogus_encode, /*encode message */ + NULL, /*copy the native value */ + H5O_bogus_size, /*raw message size */ + NULL, /*free internal memory */ + NULL, /*free method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_bogus_debug, /*debug the message */ +}}; + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + + +/*------------------------------------------------------------------------- + * Function: H5O_bogus_decode + * + * Purpose: Decode a "bogus" message and return a pointer to a new + * native message struct. + * + * Return: Success: Ptr to new message in native struct. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 21 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_bogus_decode(H5F_t UNUSED *f, const uint8_t *p, + H5O_shared_t UNUSED *sh) +{ + H5O_bogus_t *mesg=NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER(H5O_bogus_decode, NULL); + + /* check args */ + assert(f); + assert(p); + assert(!sh); + + /* Allocate the bogus message */ + if (NULL==(mesg = H5MM_calloc(sizeof(H5O_bogus_t)))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* decode */ + UINT32DECODE(p, mesg->u); + + /* Validate the bogus info */ + if(mesg->u!=H5O_BOGUS_VALUE) + HGOTO_ERROR (H5E_OHDR, H5E_BADVALUE, NULL, "invalid bogus value :-)"); + + /* Set return value */ + ret_value=mesg; + +done: + if(ret_value==NULL && mesg!=NULL) + H5MM_xfree(mesg); + + FUNC_LEAVE(ret_value); +} /* end H5O_bogus_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_bogus_encode + * + * Purpose: Encodes a "bogus" message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 21 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_bogus_encode(H5F_t UNUSED *f, uint8_t *p, const void UNUSED *mesg) +{ + FUNC_ENTER(H5O_bogus_encode, FAIL); + + /* check args */ + assert(f); + assert(p); + assert(mesg); + + /* encode */ + UINT32ENCODE(p, H5O_BOGUS_VALUE); + + FUNC_LEAVE(SUCCEED); +} /* end H5O_bogus_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_bogus_size + * + * Purpose: Returns the size of the raw message in bytes not + * counting the message typ or size fields, but only the data + * fields. This function doesn't take into account + * alignment. + * + * Return: Success: Message data size in bytes w/o alignment. + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 21 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_bogus_size(H5F_t UNUSED *f, const void UNUSED *mesg) +{ + FUNC_ENTER(H5O_bogus_size, 0); + + /* check args */ + assert(f); + + FUNC_LEAVE(4); +} /* end H5O_bogus_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_bogus_debug + * + * Purpose: Prints debugging info for the message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 21 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_bogus_debug(H5F_t UNUSED *f, const void *_mesg, FILE *stream, + int indent, int fwidth) +{ + const H5O_bogus_t *mesg = (const H5O_bogus_t *)_mesg; + + FUNC_ENTER(H5O_name_debug, FAIL); + + /* check args */ + assert(f); + assert(mesg); + assert(stream); + assert(indent >= 0); + assert(fwidth >= 0); + + fprintf(stream, "%*s%-*s `%u'\n", indent, "", fwidth, + "Bogus Value:", mesg->u); + + FUNC_LEAVE(SUCCEED); +} +#endif /* H5O_ENABLE_BOGUS */ + + diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 651dbca..c384362 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -216,6 +216,22 @@ typedef struct H5O_layout_t { void *buf; /*buffer for compact dataset */ } H5O_layout_t; +/* Enable reading/writing "bogus" messages */ +/* #define H5O_ENABLE_BOGUS */ + +#ifdef H5O_ENABLE_BOGUS +/* + * "Bogus" Message. + */ +#define H5O_BOGUS_ID 0x0009 +H5_DLLVAR const H5O_class_t H5O_BOGUS[1]; + +#define H5O_BOGUS_VALUE 0xdeadbeef +typedef struct H5O_bogus_t { + unsigned u; /* Hold the bogus info */ +} H5O_bogus_t; +#endif /* H5O_ENABLE_BOGUS */ + /* * Filter pipeline message. */ @@ -362,6 +378,10 @@ H5_DLL int H5O_append(H5F_t *f, H5O_t *oh, const H5O_class_t *type, unsigned flags, const void *mesg); H5_DLL herr_t H5O_touch(H5G_entry_t *ent, hbool_t force); H5_DLL herr_t H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force); +#ifdef H5O_ENABLE_BOGUS +H5_DLL herr_t H5O_bogus(H5G_entry_t *ent); +H5_DLL herr_t H5O_bogus_oh(H5F_t *f, H5O_t *oh); +#endif /* H5O_ENABLE_BOGUS */ H5_DLL herr_t H5O_remove(H5G_entry_t *ent, const H5O_class_t *type, int sequence); H5_DLL herr_t H5O_reset(const H5O_class_t *type, void *native); diff --git a/src/Makefile.in b/src/Makefile.in index cb9927b..95a0fc5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -32,14 +32,14 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcontig.c \ H5Fcompact.c H5Fistore.c H5Fseq.c H5FD.c H5FDcore.c H5FDfamily.c \ H5FDgass.c H5FDlog.c H5FDmpio.c H5FDmpiposix.c H5FDmulti.c H5FDsec2.c \ H5FDsrb.c H5FDstdio.c H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c \ - H5FPserver.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c \ - H5I.c H5MF.c H5MM.c H5O.c H5Oattr.c H5Ocont.c H5Odtype.c H5Oefl.c \ - H5Ofill.c H5Ofphdf5.c H5Olayout.c H5Omtime.c H5Oname.c H5Onull.c \ - H5Opline.c H5Oplist.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c \ - H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5R.c H5RS.c H5S.c H5Sall.c \ - H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c H5Sselect.c H5ST.c H5T.c \ - H5Tbit.c H5Tconv.c H5Tinit.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c \ - H5Zdeflate.c H5Zshuffle.c + H5FPserver.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c \ + H5I.c H5MF.c H5MM.c H5O.c H5Oattr.c H5Obogus.c H5Ocont.c H5Odtype.c \ + H5Oefl.c H5Ofill.c H5Ofphdf5.c H5Olayout.c H5Omtime.c H5Oname.c \ + H5Onull.c H5Opline.c H5Oplist.c H5Osdspace.c H5Oshared.c H5Ostab.c \ + H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5R.c H5RS.c H5S.c \ + H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c H5Sselect.c H5ST.c \ + H5T.c H5Tbit.c H5Tconv.c H5Tinit.c H5Tvlen.c H5TB.c H5TS.c H5V.c \ + H5Z.c H5Zdeflate.c H5Zshuffle.c LIB_OBJ=$(LIB_SRC:.c=.lo) diff --git a/test/ohdr.c b/test/ohdr.c index ddd4ed6..3884e1a 100644 --- a/test/ohdr.c +++ b/test/ohdr.c @@ -20,6 +20,11 @@ const char *FILENAME[] = { NULL }; +/* The tbogus.h5 is generated from gen_bogus.c in HDF5 'test' directory. + * To get this data file, define H5O_ENABLE_BOGUS in src/H5Oprivate, rebuild + * the library and simply compile gen_bogus.c with that HDF5 library and run it. */ +#define FILE_BOGUS "tbogus.h5" + /*------------------------------------------------------------------------- * Function: main @@ -41,6 +46,7 @@ int main(void) { hid_t fapl=-1, file=-1; + hid_t dset=-1; H5F_t *f=NULL; char filename[1024]; H5G_entry_t oh_ent; @@ -267,6 +273,31 @@ main(void) if (H5Fclose(file)<0) goto error; PASSED(); + /* Test reading dataset with undefined object header message */ + TESTING("reading object with unknown header message"); + { + char testfile[512]=""; + char *srcdir = getenv("srcdir"); + + /* Build path to test file */ + if (srcdir && ((HDstrlen(srcdir) + HDstrlen(FILE_BOGUS) + 1) < sizeof(testfile))){ + HDstrcpy(testfile, srcdir); + HDstrcat(testfile, "/"); + } + HDstrcat(testfile, FILE_BOGUS); + + if ((file=H5Fopen(testfile, H5F_ACC_RDONLY, fapl))<0) + goto error; + + /* Open the dataset with the unknown header message (generated with gen_bogus.c) */ + if((dset=H5Dopen(file,"/Dataset1"))<0) + goto error; + if (H5Dclose(dset)<0) goto error; + + if (H5Fclose(file)<0) goto error; + } + PASSED(); + puts("All object header tests passed."); h5_cleanup(FILENAME, fapl); return 0; diff --git a/test/tbogus.h5 b/test/tbogus.h5 Binary files differnew file mode 100644 index 0000000..ddc3b65 --- /dev/null +++ b/test/tbogus.h5 |