@@ -731,7 +731,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
}
start_offset = iso_td.offset[relative_frame_number];
- next_offset = iso_td.offset[relative_frame_number + 1];
+ if (relative_frame_number < frame_count) {
+ next_offset = iso_td.offset[relative_frame_number + 1];
+ } else {
+ next_offset = iso_td.be;
+ }
if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
((relative_frame_number < frame_count) &&
@@ -764,7 +768,12 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
}
} else {
/* Last packet in the ISO TD */
- end_addr = iso_td.be;
+ end_addr = next_offset;
+ }
+
+ if (start_addr > end_addr) {
+ trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr);
+ return 1;
}
if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
@@ -773,6 +782,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
} else {
len = end_addr - start_addr + 1;
}
+ if (len > sizeof(ohci->usb_buf)) {
+ len = sizeof(ohci->usb_buf);
+ }
if (len && dir != OHCI_TD_DIR_IN) {
if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
@@ -975,8 +987,16 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
} else {
+ if (td.cbp > td.be) {
+ trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
+ ohci_die(ohci);
+ return 1;
+ }
len = (td.be - td.cbp) + 1;
}
+ if (len > sizeof(ohci->usb_buf)) {
+ len = sizeof(ohci->usb_buf);
+ }
pktlen = len;
if (len && dir != OHCI_TD_DIR_IN) {