diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -136,9 +136,13 @@ #define ccb_state ppriv_field0 #define ccb_bp ppriv_ptr1 +/* + * According to the MMC-6 spec, 6.25.3.2.11, the lead-out is reported by + * READ_TOC as logical track 170, so at most 169 tracks may be reported. + */ struct cd_tocdata { struct ioc_toc_header header; - struct cd_toc_entry entries[100]; + struct cd_toc_entry entries[170]; }; struct cd_toc_single { @@ -1596,12 +1600,13 @@ } /* Number of TOC entries, plus leadout */ - num_entries = (toch->ending_track - toch->starting_track) + 2; - cdindex = toch->starting_track + num_entries -1; + num_entries = toch->ending_track - toch->starting_track + 2; + cdindex = toch->starting_track + num_entries - 1; if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) == CD_CCB_MEDIA_TOC_HDR) { - if (num_entries <= 0) { + if (num_entries <= 0 || + num_entries > nitems(softc->toc.entries)) { softc->flags &= ~CD_FLAG_VALID_TOC; bzero(&softc->toc, sizeof(softc->toc)); /* @@ -1838,23 +1843,19 @@ */ if (softc->flags & CD_FLAG_VALID_TOC) { union msf_lba *sentry, *eentry; + struct ioc_toc_header *th; int st, et; - if (args->end_track < - softc->toc.header.ending_track + 1) + th = &softc->toc.header; + if (args->end_track < th->ending_track + 1) args->end_track++; - if (args->end_track > - softc->toc.header.ending_track + 1) - args->end_track = - softc->toc.header.ending_track + 1; - st = args->start_track - - softc->toc.header.starting_track; - et = args->end_track - - softc->toc.header.starting_track; - if ((st < 0) - || (et < 0) - || (st > (softc->toc.header.ending_track - - softc->toc.header.starting_track))) { + if (args->end_track > th->ending_track + 1) + args->end_track = th->ending_track + 1; + st = args->start_track - th->starting_track; + et = args->end_track - th->starting_track; + if (st < 0 || et < 0 || + st > th->ending_track - th->starting_track || + et > th->ending_track - th->starting_track) { error = EINVAL; cam_periph_unlock(periph); break;