From f00c1059d9c7d61d7d5d75ad151b96fc599afdd7 Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Sat, 3 Mar 2012 10:46:42 -0500 Subject: [PATCH] pbatard flexible array for ecma_167.h header --- include/cdio/ecma_167.h | 34 +++++++++++++++++++---------- lib/udf/udf_file.c | 48 +++++++++++++++++++++++++---------------- lib/udf/udf_fs.c | 8 +++---- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/include/cdio/ecma_167.h b/include/cdio/ecma_167.h index 78da7ae0..62c75090 100644 --- a/include/cdio/ecma_167.h +++ b/include/cdio/ecma_167.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2006, 2008 Rocky Bernstein + Copyright (c) 2005, 2006, 2008, 2012 Rocky Bernstein Copyright (c) 2001-2002 Ben Fennema This program is free software: you can redistribute it and/or modify @@ -499,9 +499,11 @@ struct logvol_integrity_desc_s udf_Uint8_t logvol_contents_use[32]; udf_Uint32_t i_partitions; udf_Uint32_t imp_use_len; - udf_Uint32_t freespace_table[0]; - udf_Uint32_t size_table[0]; - udf_Uint8_t imp_use[0]; + 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]; + } u; } GNUC_PACKED; /** Integrity Type (ECMA 167r3 3/10.10.3) */ @@ -571,9 +573,11 @@ struct udf_fileid_desc_s udf_Uint8_t i_file_id; udf_long_ad_t icb; udf_Uint16_t i_imp_use; - udf_Uint8_t imp_use[0]; - udf_Uint8_t file_id[0]; - udf_Uint8_t padding[0]; + 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]; + } u; } GNUC_PACKED; typedef struct udf_fileid_desc_s udf_fileid_desc_t; @@ -727,8 +731,14 @@ struct udf_file_entry_s udf_Uint64_t unique_ID; udf_Uint32_t i_extended_attr; udf_Uint32_t i_alloc_descs; - udf_Uint8_t ext_attr[0]; - udf_Uint8_t alloc_descs[0]; + /* The following union allows file entry reuse without worrying + about overflows, by ensuring the struct is always the + maximum possible size allowed by the specs: one UDF block. */ + union { + udf_Uint8_t ext_attr[0]; + udf_Uint8_t alloc_descs[0]; + udf_Uint8_t pad_to_one_block[2048-176]; + } u; } GNUC_PACKED; typedef struct udf_file_entry_s udf_file_entry_t; @@ -985,8 +995,10 @@ struct extended_file_entry udf_Uint64_t unique_ID; udf_Uint32_t length_extended_attr; udf_Uint32_t length_alloc_descs; - udf_Uint8_t ext_attr[0]; - udf_Uint8_t alloc_descs[0]; + union { /* MSVC workaround for multiple zero sized arrays */ + udf_Uint8_t ext_attr[0]; + udf_Uint8_t alloc_descs[0]; + } u; } GNUC_PACKED; PRAGMA_END_PACKED diff --git a/lib/udf/udf_file.c b/lib/udf/udf_file.c index ee766a84..d969dcf0 100644 --- a/lib/udf/udf_file.c +++ b/lib/udf/udf_file.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2005, 2006, 2008, 2010 Rocky Bernstein + Copyright (C) 2005, 2006, 2008, 2010, 2012 Rocky Bernstein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,9 @@ # include #endif +#ifdef HAVE_STDIO_H #include /* Remove when adding cdio/logging.h */ +#endif /* Useful defines */ @@ -34,7 +36,7 @@ #define CEILING(x, y) ((x+(y-1))/y) #define GETICB(offset) \ - &p_udf_fe->alloc_descs[offset] + &p_udf_fe->u.alloc_descs[offset] const char * udf_get_filename(const udf_dirent_t *p_udf_dirent) @@ -44,8 +46,7 @@ udf_get_filename(const udf_dirent_t *p_udf_dirent) return p_udf_dirent->psz_name; } -/* Get UDF File Entry. However we do NOT get the variable-length extended - attributes. */ +/* Copy an UDF File Entry into a Directory Entry structure. */ bool udf_get_file_entry(const udf_dirent_t *p_udf_dirent, /*out*/ udf_file_entry_t *p_udf_fe) @@ -116,16 +117,21 @@ offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, &p_udf_dirent->fe; const udf_icbtag_t *p_icb_tag = &p_udf_fe->icb_tag; const uint16_t strat_type= uint16_from_le(p_icb_tag->strat_type); - + + if (i_offset < 0) { + cdio_warn("Negative offset value"); + return CDIO_INVALID_LBA; + } + switch (strat_type) { case 4096: - printf("Cannot deal with strategy4096 yet!\n"); + cdio_warn("Cannot deal with strategy4096 yet!"); return CDIO_INVALID_LBA; break; case ICBTAG_STRATEGY_TYPE_4: { - uint32_t icblen = 0; - lba_t lsector; + off_t icblen = 0; + uint64_t lsector; int ad_offset, ad_num = 0; uint16_t addr_ilk = uint16_from_le(p_icb_tag->flags&ICBTAG_FLAG_AD_MASK); @@ -142,7 +148,7 @@ offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, i_offset -= icblen; ad_offset = sizeof(udf_short_ad_t) * ad_num; if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) { - printf("File offset out of bounds\n"); + cdio_warn("File offset out of bounds"); return CDIO_INVALID_LBA; } p_icb = (udf_short_ad_t *) @@ -169,7 +175,7 @@ offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, i_offset -= icblen; ad_offset = sizeof(udf_long_ad_t) * ad_num; if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) { - printf("File offset out of bounds\n"); + cdio_warn("File offset out of bounds"); return CDIO_INVALID_LBA; } p_icb = (udf_long_ad_t *) @@ -191,21 +197,25 @@ offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, * allocation descriptor field of the file entry. */ *pi_max_size = 0; - printf("Don't know how to data in ICB handle yet\n"); + cdio_warn("Don't know how to data in ICB handle yet"); return CDIO_INVALID_LBA; case ICBTAG_FLAG_AD_EXTENDED: - printf("Don't know how to handle extended addresses yet\n"); + cdio_warn("Don't know how to handle extended addresses yet"); return CDIO_INVALID_LBA; default: - printf("Unsupported allocation descriptor %d\n", addr_ilk); + cdio_warn("Unsupported allocation descriptor %d", addr_ilk); + return CDIO_INVALID_LBA; + } + + *pi_lba = (lba_t)lsector + p_udf->i_part_start; + if (*pi_lba < 0) { + cdio_warn("Negative LBA value"); return CDIO_INVALID_LBA; } - - *pi_lba = lsector + p_udf->i_part_start; return *pi_lba; } default: - printf("Unknown strategy type %d\n", strat_type); + cdio_warn("Unknown strategy type %d", strat_type); return DRIVER_OP_ERROR; } } @@ -238,9 +248,9 @@ udf_read_block(const udf_dirent_t *p_udf_dirent, void * buf, size_t count) if (i_lba != CDIO_INVALID_LBA) { uint32_t i_max_blocks = CEILING(i_max_size, UDF_BLOCKSIZE); if ( i_max_blocks < count ) { - fprintf(stderr, "Warning: read count %u is larger than %u extent size.\n", - count, i_max_blocks); - fprintf(stderr, "Warning: read count truncated to %u\n", count); + cdio_warn("read count %u is larger than %u extent size.", + (unsigned int)count, i_max_blocks); + cdio_warn("read count truncated to %u", (unsigned int)count); count = i_max_blocks; } ret = udf_read_sectors(p_udf, buf, i_lba, count); diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c index b8209f17..98830cf7 100644 --- a/lib/udf/udf_fs.c +++ b/lib/udf/udf_fs.c @@ -159,7 +159,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe, { /* The allocation descriptor field is filled with short_ad's. */ udf_short_ad_t *p_ad = (udf_short_ad_t *) - (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr); + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); *start = uint32_from_le(p_ad->pos); *end = *start + @@ -171,7 +171,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe, { /* The allocation descriptor field is filled with long_ad's */ udf_long_ad_t *p_ad = (udf_long_ad_t *) - (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr); + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); *start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */ *end = *start + @@ -182,7 +182,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe, case ICBTAG_FLAG_AD_EXTENDED: { udf_ext_ad_t *p_ad = (udf_ext_ad_t *) - (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr); + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); *start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition number */ *end = *start + @@ -681,7 +681,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent) p_udf_dirent->psz_name = (char *) realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); - unicode16_decode(p_udf_dirent->fid->imp_use + unicode16_decode(p_udf_dirent->fid->u.imp_use + p_udf_dirent->fid->i_imp_use, i_len, p_udf_dirent->psz_name); }