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
This commit is contained in:
Pete Batard
2012-03-05 18:08:03 +00:00
parent a7d3059857
commit d7296d5ec0
2 changed files with 42 additions and 15 deletions

View File

@@ -498,11 +498,20 @@ struct logvol_integrity_desc_s
udf_extent_ad_t next_integrity_ext; udf_extent_ad_t next_integrity_ext;
udf_Uint8_t logvol_contents_use[32]; udf_Uint8_t logvol_contents_use[32];
udf_Uint32_t i_partitions; udf_Uint32_t i_partitions;
udf_Uint32_t imp_use_len; union { /* Same MSVC workaround as with struct udf_fileid_desc_s */
union { /* MSVC workaround for multiple zero sized arrays */ udf_Uint32_t imp_use_len;
udf_Uint32_t freespace_table[0]; struct {
udf_Uint32_t size_table[0]; udf_Uint32_t unused;
udf_Uint8_t imp_use[0]; 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; } u;
} GNUC_PACKED; } GNUC_PACKED;
@@ -572,11 +581,25 @@ struct udf_fileid_desc_s
udf_Uint8_t file_characteristics; udf_Uint8_t file_characteristics;
udf_Uint8_t i_file_id; udf_Uint8_t i_file_id;
udf_long_ad_t icb; udf_long_ad_t icb;
udf_Uint16_t i_imp_use; /* MSVC workaround for multiple zero sized arrays
union { /* MSVC workaround for multiple zero sized arrays */ Unlike what is the case with GNU, and against logic, an union of zero
udf_Uint8_t imp_use[0]; sized arrays in the Microsoft world is not zero bytes but one byte!
udf_Uint8_t file_id[0]; Thus, for sizeof() to be consistent across platforms, we must use an
udf_Uint8_t padding[0]; 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; } u;
} GNUC_PACKED; } GNUC_PACKED;
@@ -998,6 +1021,7 @@ struct extended_file_entry
union { /* MSVC workaround for multiple zero sized arrays */ union { /* MSVC workaround for multiple zero sized arrays */
udf_Uint8_t ext_attr[0]; udf_Uint8_t ext_attr[0];
udf_Uint8_t alloc_descs[0]; udf_Uint8_t alloc_descs[0];
udf_Uint8_t pad_to_one_block[2048-216];
} u; } u;
} GNUC_PACKED; } GNUC_PACKED;

View File

@@ -634,7 +634,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
/* advance to next File Identifier Descriptor */ /* advance to next File Identifier Descriptor */
/* FIXME: need to advance file entry (fe) as well. */ /* FIXME: need to advance file entry (fe) as well. */
uint32_t ofs = 4 * 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->i_file_id + 3) / 4);
p_udf_dirent->fid = 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)) if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID))
{ {
uint32_t ofs = 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->fid->i_file_id + 3) / 4);
p_udf_dirent->dir_left -= ofs; 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; 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 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; return NULL;
}
if (strlen(p_udf_dirent->psz_name) < i_len) if (strlen(p_udf_dirent->psz_name) < i_len)
p_udf_dirent->psz_name = (char *) p_udf_dirent->psz_name = (char *)
realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1);
unicode16_decode(p_udf_dirent->fid->u.imp_use unicode16_decode(p_udf_dirent->fid->u.imp_use.data
+ p_udf_dirent->fid->i_imp_use, + p_udf_dirent->fid->u.i_imp_use,
i_len, p_udf_dirent->psz_name); i_len, p_udf_dirent->psz_name);
} }
return p_udf_dirent; return p_udf_dirent;
} }
udf_dirent_free(p_udf_dirent);
return NULL; return NULL;
} }