static inline int
ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
-{
- uint32_t prop_count = dtoh32a(data);
+{
+ uint32_t prop_count;
MTPProperties *props = NULL;
unsigned int offset = 0, i;
- if (prop_count == 0) {
- *pprops = NULL;
+ if (len < sizeof(uint32_t)) {
+ ptp_debug (params ,"must have at least 4 bytes data, not %d", len);
return 0;
}
+ prop_count = dtoh32a(data);
+ *pprops = NULL;
+ if (prop_count == 0)
+ return 0;
+
if (prop_count >= INT_MAX/sizeof(MTPProperties)) {
ptp_debug (params ,"prop_count %d is too large", prop_count);
return 0;
}
-
ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
+
data += sizeof(uint32_t);
len -= sizeof(uint32_t);
props = malloc(prop_count * sizeof(MTPProperties));
if (!props) return 0;
for (i = 0; i < prop_count; i++) {
- if (len <= 0) {
+ if (len <= (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t))) {
ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
- ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
+ ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL");
ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
qsort (props, i, sizeof(MTPProperties),_compare_func);
*pprops = props;
len -= sizeof(uint16_t);
offset = 0;
- ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
+ if (!ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype)) {
+ ptp_debug (params ,"unpacking DPV of property %d encountered insufficient buffer. attack?", i);
+ qsort (props, i, sizeof(MTPProperties),_compare_func);
+ *pprops = props;
+ return i;
+ }
data += offset;
len -= offset;
}