diff options
author | Nikias Bassen | 2017-10-26 11:51:03 +0200 |
---|---|---|
committer | Nikias Bassen | 2017-10-26 11:51:03 +0200 |
commit | b398a9ab735ea63ffd17d7c063503521460ed83f (patch) | |
tree | beed060d7af07317b4d2393c3d0460eb3fdc47b0 /src | |
parent | 2ebf47816089d0053daf6b919089000fbe36a338 (diff) | |
download | libirecovery-b398a9ab735ea63ffd17d7c063503521460ed83f.tar.gz libirecovery-b398a9ab735ea63ffd17d7c063503521460ed83f.tar.bz2 |
irecv_send_buffer: Fix DFU file upload failure due to oversized last packet
In DFU mode the last packet contains the checksum for the transferred data
(and 12 additional bytes, total 16 bytes). If the last packet is larger than
2032 bytes we would send a packet that is larger than the packet size of 2048
bytes which would make the file upload fail.
This is especially the case for the iOS 11.0.x iBSS for the iPhone 8.
With this commit the size is checked and if it would be larger than the
packet size, we split the data portion and the checksum into two separate
packets. It might even be safe to always split the last packet into data
and checksum, but until this is proven to work with all (especially older
devices) we just split when we detect the oversized packet for now.
Diffstat (limited to 'src')
-rw-r--r-- | src/libirecovery.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index 69f1d90..a255d78 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -1760,6 +1760,15 @@ IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* dfu_hash_step(h1, buffer[i*packet_size + j]); } if (i+1 == packets) { + if (size+16 > packet_size) { + bytes = irecv_usb_control_transfer(client, 0x21, 1, i, 0, &buffer[i * packet_size], size, USB_TIMEOUT); + if (bytes != size) { + return IRECV_E_USB_UPLOAD; + } + count += size; + size = 0; + } + for (j = 0; j < 2; j++) { dfu_hash_step(h1, dfu_xbuf[j*6 + 0]); dfu_hash_step(h1, dfu_xbuf[j*6 + 1]); @@ -1770,7 +1779,9 @@ IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* } char* newbuf = (char*)malloc(size + 16); - memcpy(newbuf, &buffer[i * packet_size], size); + if (size > 0) { + memcpy(newbuf, &buffer[i * packet_size], size); + } memcpy(newbuf+size, dfu_xbuf, 12); newbuf[size+12] = h1 & 0xFF; newbuf[size+13] = (h1 >> 8) & 0xFF; |