From: Pali Rohár Date: Wed, 9 Dec 2020 00:22:28 +0000 (+0100) Subject: libblkid: iso9660: fix parsing images which do not have Primary Volume Descriptor... X-Git-Tag: v2.37-rc1~234 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4bfcb1fc4af2345f055876dabc7be778bcbf4b70;p=thirdparty%2Futil-linux.git libblkid: iso9660: fix parsing images which do not have Primary Volume Descriptor as the first ECMA 119 (ISO 9660) does not mandate that Primary Volume Descriptor needs to be the first in Volume Descriptor Set sequence. Move assignment of labels outside of the for-loop and correctly detects Primary Volume Descriptor via its type (0x01) at any position in sequence. Signed-off-by: Pali Rohár --- diff --git a/libblkid/src/superblocks/iso9660.c b/libblkid/src/superblocks/iso9660.c index 66d11356d7..1a296e217d 100644 --- a/libblkid/src/superblocks/iso9660.c +++ b/libblkid/src/superblocks/iso9660.c @@ -63,8 +63,8 @@ struct boot_record { #define ISO_SUPERBLOCK_OFFSET 0x8000 #define ISO_SECTOR_SIZE 0x800 -#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE) #define ISO_VD_BOOT_RECORD 0x0 +#define ISO_VD_PRIMARY 0x1 #define ISO_VD_SUPPLEMENTARY 0x2 #define ISO_VD_END 0xff #define ISO_VD_MAX 16 @@ -169,97 +169,81 @@ static int is_str_empty(const unsigned char *str, size_t len) /* iso9660 [+ Microsoft Joliet Extension] */ static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag) { - struct iso_volume_descriptor *iso; - unsigned char label[32]; + struct boot_record *boot = NULL; + struct iso_volume_descriptor *pvd = NULL; + struct iso_volume_descriptor *joliet = NULL; int i; uint64_t off; if (blkid_probe_get_hint(pr, mag->hoff, &off) < 0) off = 0; - if (off % 2048) + if (off % ISO_SECTOR_SIZE) return 1; if (strcmp(mag->magic, "CDROM") == 0) return probe_iso9660_hsfs(pr, mag); - iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor); - if (!iso) - return errno ? -errno : 1; - - memcpy(label, iso->volume_id, sizeof(label)); - - blkid_probe_set_block_size(pr, 2048); - - blkid_probe_set_id_label(pr, "SYSTEM_ID", - iso->system_id, sizeof(iso->system_id)); - - if (!is_str_empty(iso->publisher_id, sizeof(iso->publisher_id)) && iso->publisher_id[0] != '_') - blkid_probe_set_id_label(pr, "PUBLISHER_ID", - iso->publisher_id, sizeof(iso->publisher_id)); - - if (!is_str_empty(iso->application_id, sizeof(iso->application_id)) && iso->application_id[0] != '_') - blkid_probe_set_id_label(pr, "APPLICATION_ID", - iso->application_id, sizeof(iso->application_id)); - - /* create an UUID using the modified/created date */ - if (! probe_iso9660_set_uuid(pr, &iso->modified)) - probe_iso9660_set_uuid(pr, &iso->created); - - /* Joliet Extension and Boot Record */ - off += ISO_VD_OFFSET; - for (i = 0; i < ISO_VD_MAX; i++) { - struct boot_record *boot= (struct boot_record *) + for (i = 0, off += ISO_SUPERBLOCK_OFFSET; i < ISO_VD_MAX && (!boot || !pvd || !joliet); i++, off += ISO_SECTOR_SIZE) { + unsigned char *desc = blkid_probe_get_buffer(pr, off, max(sizeof(struct boot_record), sizeof(struct iso_volume_descriptor))); - if (boot == NULL || boot->vd_type == ISO_VD_END) + if (desc == NULL || desc[0] == ISO_VD_END) break; - - if (boot->vd_type == ISO_VD_BOOT_RECORD) { - blkid_probe_set_id_label(pr, "BOOT_SYSTEM_ID", - boot->boot_system_id, - sizeof(boot->boot_system_id)); - off += ISO_SECTOR_SIZE; - continue; + else if (!boot && desc[0] == ISO_VD_BOOT_RECORD) + boot = (struct boot_record *)desc; + else if (!pvd && desc[0] == ISO_VD_PRIMARY) + pvd = (struct iso_volume_descriptor *)desc; + else if (!joliet && desc[0] == ISO_VD_SUPPLEMENTARY) { + joliet = (struct iso_volume_descriptor *)desc; + if (memcmp(joliet->escape_sequences, "%/@", 3) != 0 && + memcmp(joliet->escape_sequences, "%/C", 3) != 0 && + memcmp(joliet->escape_sequences, "%/E", 3) != 0) + joliet = NULL; } + } - /* Not a Boot record, lets see if its supplementary volume descriptor */ - iso = (struct iso_volume_descriptor *) boot; - - if (iso->vd_type != ISO_VD_SUPPLEMENTARY) { - off += ISO_SECTOR_SIZE; - continue; - } + if (!pvd) + return errno ? -errno : 1; - if (memcmp(iso->escape_sequences, "%/@", 3) == 0 || - memcmp(iso->escape_sequences, "%/C", 3) == 0 || - memcmp(iso->escape_sequences, "%/E", 3) == 0) { + blkid_probe_set_block_size(pr, ISO_SECTOR_SIZE); - blkid_probe_set_version(pr, "Joliet Extension"); + blkid_probe_set_id_label(pr, "SYSTEM_ID", + pvd->system_id, sizeof(pvd->system_id)); - /* Is the Joliet (UTF16BE) label equal to the label in - * the PVD? If yes, use PVD label. The Joliet version - * of the label could be trimmed (because UTF16..). - */ - if (ascii_eq_utf16be(label, iso->volume_id, 32)) - break; + if (!is_str_empty(pvd->publisher_id, sizeof(pvd->publisher_id)) && pvd->publisher_id[0] != '_') + blkid_probe_set_id_label(pr, "PUBLISHER_ID", + pvd->publisher_id, sizeof(pvd->publisher_id)); - blkid_probe_set_utf8label(pr, - iso->volume_id, - sizeof(iso->volume_id), - UL_ENCODE_UTF16BE); - goto has_label; - } - off += ISO_SECTOR_SIZE; - } + if (!is_str_empty(pvd->application_id, sizeof(pvd->application_id)) && pvd->application_id[0] != '_') + blkid_probe_set_id_label(pr, "APPLICATION_ID", + pvd->application_id, sizeof(pvd->application_id)); - /* Joliet not found, let use standard iso label */ - blkid_probe_set_label(pr, label, sizeof(label)); + /* create an UUID using the modified/created date */ + if (! probe_iso9660_set_uuid(pr, &pvd->modified)) + probe_iso9660_set_uuid(pr, &pvd->created); + + if (boot) + blkid_probe_set_id_label(pr, "BOOT_SYSTEM_ID", + boot->boot_system_id, + sizeof(boot->boot_system_id)); + + if (joliet) + blkid_probe_set_version(pr, "Joliet Extension"); + + /* Is the Joliet (UTF16BE) label equal to the label in + * the PVD? If yes, use PVD label. The Joliet version + * of the label could be trimmed (because UTF16..). + */ + if (joliet && !ascii_eq_utf16be(pvd->volume_id, joliet->volume_id, sizeof(pvd->volume_id))) + blkid_probe_set_utf8label(pr, joliet->volume_id, sizeof(joliet->volume_id), UL_ENCODE_UTF16BE); + else + /* Joliet not found, let use standard primary label */ + blkid_probe_set_label(pr, pvd->volume_id, sizeof(pvd->volume_id)); -has_label: return 0; }