From d7296d5ec0421e4f5ea534161fe5cbfbfbe57d4f Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Mon, 5 Mar 2012 18:08:03 +0000 Subject: [PATCH] Apply MSVC compatibility workaround to ecma_167.h * An union of empty arrays is not size zero in MSVC * this causes issues with various sections of the UDF code that use sizeof and can prevent structures from being read properly * group empty array unions with at least one non zero-sized member --- include/cdio/ecma_167.h | 44 +++++++++++++++++++++++++++++++---------- lib/udf/udf_fs.c | 13 +++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/cdio/ecma_167.h b/include/cdio/ecma_167.h index 62c75090..d6cb2c8f 100644 --- a/include/cdio/ecma_167.h +++ b/include/cdio/ecma_167.h @@ -498,11 +498,20 @@ struct logvol_integrity_desc_s udf_extent_ad_t next_integrity_ext; udf_Uint8_t logvol_contents_use[32]; udf_Uint32_t i_partitions; - udf_Uint32_t imp_use_len; - union { /* MSVC workaround for multiple zero sized arrays */ - udf_Uint32_t freespace_table[0]; - udf_Uint32_t size_table[0]; - udf_Uint8_t imp_use[0]; + union { /* Same MSVC workaround as with struct udf_fileid_desc_s */ + udf_Uint32_t imp_use_len; + struct { + udf_Uint32_t unused; + udf_Uint32_t data[0]; + } freespace_table; + struct { + udf_Uint32_t unused; + udf_Uint32_t data[0]; + } size_table; + struct { + udf_Uint32_t unused; + udf_Uint32_t data[0]; + } imp_use; } u; } GNUC_PACKED; @@ -572,11 +581,25 @@ struct udf_fileid_desc_s udf_Uint8_t file_characteristics; udf_Uint8_t i_file_id; udf_long_ad_t icb; - udf_Uint16_t i_imp_use; - union { /* MSVC workaround for multiple zero sized arrays */ - udf_Uint8_t imp_use[0]; - udf_Uint8_t file_id[0]; - udf_Uint8_t padding[0]; + /* MSVC workaround for multiple zero sized arrays + Unlike what is the case with GNU, and against logic, an union of zero + sized arrays in the Microsoft world is not zero bytes but one byte! + Thus, for sizeof() to be consistent across platforms, we must use an + ugly workaround that attaches the union to the last non-zero member. */ + union { + udf_Uint16_t i_imp_use; + struct { + udf_Uint16_t unused; + udf_Uint8_t data[0]; + } imp_use; + struct { + udf_Uint16_t unused; + udf_Uint8_t data[0]; + } file_id; + struct { + udf_Uint16_t unused; + udf_Uint8_t data[0]; + } padding; } u; } GNUC_PACKED; @@ -998,6 +1021,7 @@ struct extended_file_entry union { /* MSVC workaround for multiple zero sized arrays */ udf_Uint8_t ext_attr[0]; udf_Uint8_t alloc_descs[0]; + udf_Uint8_t pad_to_one_block[2048-216]; } u; } GNUC_PACKED; diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c index 98830cf7..5f5add7b 100644 --- a/lib/udf/udf_fs.c +++ b/lib/udf/udf_fs.c @@ -634,7 +634,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent) /* advance to next File Identifier Descriptor */ /* FIXME: need to advance file entry (fe) as well. */ uint32_t ofs = 4 * - ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->i_imp_use + ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->u.i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->fid = @@ -661,7 +661,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent) if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID)) { uint32_t ofs = - 4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->i_imp_use + 4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->u.i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->dir_left -= ofs; @@ -674,19 +674,22 @@ udf_readdir(udf_dirent_t *p_udf_dirent) const unsigned int i_len = p_udf_dirent->fid->i_file_id; if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start - + p_udf_dirent->fid->icb.loc.lba, 1)) + + p_udf_dirent->fid->icb.loc.lba, 1)) { + udf_dirent_free(p_udf_dirent); return NULL; + } if (strlen(p_udf_dirent->psz_name) < i_len) p_udf_dirent->psz_name = (char *) realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); - unicode16_decode(p_udf_dirent->fid->u.imp_use - + p_udf_dirent->fid->i_imp_use, + unicode16_decode(p_udf_dirent->fid->u.imp_use.data + + p_udf_dirent->fid->u.i_imp_use, i_len, p_udf_dirent->psz_name); } return p_udf_dirent; } + udf_dirent_free(p_udf_dirent); return NULL; }