summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2017-10-26 11:51:03 +0200
committerGravatar Nikias Bassen2017-10-26 11:51:03 +0200
commitb398a9ab735ea63ffd17d7c063503521460ed83f (patch)
treebeed060d7af07317b4d2393c3d0460eb3fdc47b0
parent2ebf47816089d0053daf6b919089000fbe36a338 (diff)
downloadlibirecovery-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.
-rw-r--r--src/libirecovery.c13
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;