aboutsummaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorIsaac Lozano <109lozanoi@gmail.com>2016-08-06 03:06:01 -0700
committerGerd Hoffmann <kraxel@redhat.com>2016-09-14 11:17:06 +0200
commit8a5865f331028e66b4ed233129d7a914c2d5bfc7 (patch)
tree86d156bbf9942457f33b9784df7bfc8232bc5ee0 /hw/usb
parentb53dd4495ced2432a0b652ea895e651d07336f7e (diff)
usb-mtp: fix sending files larger than 4gb
MTP requires that if a file is larger than 4gb or if sending data larger than 4gb, that the length field be set to 0xFFFFFFFF. Also widened a couple variables to prevent overflow errors. Signed-off-by: Isaac Lozano <109lozanoi@gmail.com> Message-id: 01ad8ec7775f58575801ac3f13716f553a16815e.1470477265.git.109lozanoi@gmail.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/dev-mtp.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1be85ae75a..869d244530 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -115,8 +115,8 @@ struct MTPControl {
struct MTPData {
uint16_t code;
uint32_t trans;
- uint32_t offset;
- uint32_t length;
+ uint64_t offset;
+ uint64_t length;
uint32_t alloc;
uint8_t *data;
bool first;
@@ -883,7 +883,12 @@ static MTPData *usb_mtp_get_object_info(MTPState *s, MTPControl *c,
usb_mtp_add_u32(d, QEMU_STORAGE_ID);
usb_mtp_add_u16(d, o->format);
usb_mtp_add_u16(d, 0);
- usb_mtp_add_u32(d, o->stat.st_size);
+
+ if (o->stat.st_size > 0xFFFFFFFF) {
+ usb_mtp_add_u32(d, 0xFFFFFFFF);
+ } else {
+ usb_mtp_add_u32(d, o->stat.st_size);
+ }
usb_mtp_add_u16(d, 0);
usb_mtp_add_u32(d, 0);
@@ -1193,10 +1198,15 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
}
if (s->data_in != NULL) {
MTPData *d = s->data_in;
- int dlen = d->length - d->offset;
+ uint64_t dlen = d->length - d->offset;
if (d->first) {
trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length);
- container.length = cpu_to_le32(d->length + sizeof(container));
+ if (d->length + sizeof(container) > 0xFFFFFFFF) {
+ container.length = cpu_to_le32(0xFFFFFFFF);
+ } else {
+ container.length =
+ cpu_to_le32(d->length + sizeof(container));
+ }
container.type = cpu_to_le16(TYPE_DATA);
container.code = cpu_to_le16(d->code);
container.trans = cpu_to_le32(d->trans);