diff --git a/src/camlib.h b/src/camlib.h index 26f527e..c350d56 100644 --- a/src/camlib.h +++ b/src/camlib.h @@ -27,7 +27,7 @@ void ptp_verbose_log(char *fmt, ...); __attribute__ ((noreturn)) void ptp_panic(char *fmt, ...); -// 4mb recommended default buffer size +// 1mb default buffer size #define CAMLIB_DEFAULT_SIZE 1000000 /// @brief Camlib library errors, not PTP return codes @@ -267,6 +267,7 @@ int ptp_read_string(uint8_t *dat, char *string, int max); int ptp_write_string(uint8_t *dat, char *string); int ptp_write_utf8_string(void *dat, char *string); int ptp_read_uint16_array(uint8_t *dat, uint16_t *buf, int max, int *length); +int ptp_read_uint16_array_s(uint8_t *bs, uint8_t *be, uint16_t *buf, int max, int *length); inline static int ptp_write_u8 (void *buf, uint8_t out) { ((uint8_t *)buf)[0] = out; return 1; } inline static int ptp_write_u16(void *buf, uint16_t out) { ((uint16_t *)buf)[0] = out; return 2; } inline static int ptp_write_u32(void *buf, uint32_t out) { ((uint32_t *)buf)[0] = out; return 4; } diff --git a/src/data.c b/src/data.c index 8b24896..32adcfb 100644 --- a/src/data.c +++ b/src/data.c @@ -263,27 +263,27 @@ void *ptp_pack_chdk_upload_file(struct PtpRuntime *r, char *in, char *out, int * } int ptp_parse_device_info(struct PtpRuntime *r, struct PtpDeviceInfo *di) { - uint8_t *e = ptp_get_payload(r); + uint8_t *b = ptp_get_payload(r); + uint8_t *e = b + r->data_length; - e += ptp_read_u16(e, &di->standard_version); - e += ptp_read_u32(e, &di->vendor_ext_id); - e += ptp_read_u16(e, &di->version); + b += ptp_read_u16(b, &di->standard_version); + b += ptp_read_u32(b, &di->vendor_ext_id); + b += ptp_read_u16(b, &di->version); - e += ptp_read_string(e, di->extensions, sizeof(di->extensions)); - - e += ptp_read_u16(e, &di->functional_mode); + b += ptp_read_string(b, di->extensions, sizeof(di->extensions)); + b += ptp_read_u16(b, &di->functional_mode); - e += ptp_read_uint16_array(e, di->ops_supported, sizeof(di->ops_supported) / 2, &di->ops_supported_length); - e += ptp_read_uint16_array(e, di->events_supported, sizeof(di->events_supported) / 2, &di->events_supported_length); - e += ptp_read_uint16_array(e, di->props_supported, sizeof(di->props_supported) / 2, &di->props_supported_length); - e += ptp_read_uint16_array(e, di->capture_formats, sizeof(di->capture_formats) / 2, &di->capture_formats_length); - e += ptp_read_uint16_array(e, di->playback_formats, sizeof(di->playback_formats) / 2, &di->playback_formats_length); + b += ptp_read_uint16_array_s(b, e, di->ops_supported, sizeof(di->ops_supported) / 2, &di->ops_supported_length); + b += ptp_read_uint16_array_s(b, e, di->events_supported, sizeof(di->events_supported) / 2, &di->events_supported_length); + b += ptp_read_uint16_array_s(b, e, di->props_supported, sizeof(di->props_supported) / 2, &di->props_supported_length); + b += ptp_read_uint16_array_s(b, e, di->capture_formats, sizeof(di->capture_formats) / 2, &di->capture_formats_length); + b += ptp_read_uint16_array_s(b, e, di->playback_formats, sizeof(di->playback_formats) / 2, &di->playback_formats_length); - e += ptp_read_string(e, di->manufacturer, sizeof(di->manufacturer)); - e += ptp_read_string(e, di->model, sizeof(di->model)); + b += ptp_read_string(b, di->manufacturer, sizeof(di->manufacturer)); + b += ptp_read_string(b, di->model, sizeof(di->model)); - e += ptp_read_string(e, di->device_version, sizeof(di->device_version)); - e += ptp_read_string(e, di->serial_number, sizeof(di->serial_number)); + b += ptp_read_string(b, di->device_version, sizeof(di->device_version)); + b += ptp_read_string(b, di->serial_number, sizeof(di->serial_number)); r->di = di; // set last parsed di diff --git a/src/log.c b/src/log.c index 17aed5f..e044c40 100644 --- a/src/log.c +++ b/src/log.c @@ -21,6 +21,6 @@ void ptp_panic(char *fmt, ...) { va_start(args, fmt); vprintf(fmt, args); va_end(args); - + fflush(stdout); abort(); } diff --git a/src/packet.c b/src/packet.c index b550623..e1498ca 100644 --- a/src/packet.c +++ b/src/packet.c @@ -9,6 +9,14 @@ #include #include +static void boundcheck(uint8_t *bs, uint8_t *be, int size) { + if (be == NULL) return; + if ((uintptr_t)bs > (uintptr_t)be) ptp_panic("PTP: bs after be\n"); + if (((uintptr_t)be - (uintptr_t)bs) < (uintptr_t)size) { + ptp_panic("PTP: buffer overflow %p-%p (%u)\n", bs, be, size); + } +} + // Read standard UTF16 string int ptp_read_string(uint8_t *d, char *string, int max) { int of = 0; @@ -48,6 +56,21 @@ int ptp_read_uint16_array(uint8_t *dat, uint16_t *buf, int max, int *length) { return of; } +int ptp_read_uint16_array_s(uint8_t *bs, uint8_t *be, uint16_t *buf, int max, int *length) { + int of = 0; + uint32_t n; + of += ptp_read_u32(bs + of, &n); + boundcheck(bs, be, 4 * n + 4); + for (uint32_t i = 0; i < n; i++) { + if (i >= max) { + ptp_panic("ptp_read_uint16_array overflow\n"); + } else { + of += ptp_read_u16(bs + of, &buf[i]); + } + } + return of; +} + // Write standard PTP wchar string int ptp_write_string(uint8_t *dat, char *string) { int of = 0;