diff options
author | Martin Pitt <martin.pitt@ubuntu.com> | 2010-10-05 17:56:19 +0200 |
---|---|---|
committer | Martin Pitt <martin.pitt@ubuntu.com> | 2010-10-05 17:56:19 +0200 |
commit | 1ebd2a5620c93ef4698485d392c19ded675412d2 (patch) | |
tree | eebf138873734e92a3ce008f1b1fabbfbf0674b7 | |
parent | 678df8a461c7573bf423a39be383bc7b70d943df (diff) |
cdrom_id: Don't read beyond "last track" in TOC
Read the first and last track from the TOC header, and do not go beyond that
stated number of tracks when reading the TOC. Otherwise we interpret random
data which leads to bogus tracks. (Reported on an IronKey, which reported 1
data track, and 4 audio tracks which weren't actually present.)
-rw-r--r-- | extras/cdrom_id/cdrom_id.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/extras/cdrom_id/cdrom_id.c b/extras/cdrom_id/cdrom_id.c index e7a3e40a85..1b43fe43ae 100644 --- a/extras/cdrom_id/cdrom_id.c +++ b/extras/cdrom_id/cdrom_id.c @@ -712,7 +712,7 @@ static int cd_media_toc(struct udev *udev, int fd) struct scsi_cmd sc; unsigned char header[12]; unsigned char toc[2048]; - unsigned int len, i; + unsigned int len, i, num_tracks; unsigned char *p; int err; @@ -728,11 +728,13 @@ static int cd_media_toc(struct udev *udev, int fd) } len = (header[0] << 8 | header[1]) + 2; - info(udev, "READ TOC: len: %d\n", len); + info(udev, "READ TOC: len: %d, start track: %d, end track: %d\n", len, header[2], header[3]); if (len > sizeof(toc)) return -1; if (len < 2) return -1; + /* 2: first track, 3: last track */ + num_tracks = header[3] - header[2] + 1; /* empty media has no tracks */ if (len < 8) @@ -750,7 +752,10 @@ static int cd_media_toc(struct udev *udev, int fd) return -1; } - for (p = toc+4, i = 4; i < len-8; i += 8, p += 8) { + /* Take care to not iterate beyond the last valid track as specified in + * the TOC, but also avoid going beyond the TOC length, just in case + * the last track number is invalidly large */ + for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) { unsigned int block; unsigned int is_data_track; |