|
1 | 1 | /******************************************************************************* |
2 | | - * Copyright (c) 2017, 2024 IBM Corp. and others |
| 2 | + * Copyright (c) 2017, 2026 IBM Corp. and others |
3 | 3 | * |
4 | 4 | * All rights reserved. This program and the accompanying materials |
5 | 5 | * are made available under the terms of the Eclipse Public License v2.0 |
@@ -248,33 +248,54 @@ int MQTTProperties_write(char** pptr, const MQTTProperties* properties) |
248 | 248 | return rc; |
249 | 249 | } |
250 | 250 |
|
| 251 | +/** |
| 252 | + * Is there enough data remaining to read the supplied number of bytes |
| 253 | + * @param pptr current read position |
| 254 | + * @param enddata pointer to the last byte of the buffer |
| 255 | + * @param len number of bytes to be read |
| 256 | + * @return 1 if the data can be read, 0 if the buffer is too short |
| 257 | + */ |
| 258 | +static int is_enough_data(char** pptr, char* enddata, int len) |
| 259 | +{ |
| 260 | + return (enddata - (*pptr)) >= len; |
| 261 | +} |
251 | 262 |
|
252 | 263 | int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata) |
253 | 264 | { |
254 | 265 | int type = -1, |
255 | 266 | len = -1; |
256 | 267 |
|
257 | 268 | memset(prop, 0, sizeof(MQTTProperty)); |
| 269 | + if (!is_enough_data(pptr, enddata, 1)) |
| 270 | + goto exit; |
258 | 271 | prop->identifier = readChar(pptr); |
259 | 272 | type = MQTTProperty_getType(prop->identifier); |
260 | 273 | if (type >= MQTTPROPERTY_TYPE_BYTE && type <= MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR) |
261 | 274 | { |
262 | 275 | switch (type) |
263 | 276 | { |
264 | 277 | case MQTTPROPERTY_TYPE_BYTE: |
| 278 | + if (!is_enough_data(pptr, enddata, 1)) |
| 279 | + goto exit; |
265 | 280 | prop->value.byte = readChar(pptr); |
266 | 281 | len = 1; |
267 | 282 | break; |
268 | 283 | case MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER: |
| 284 | + if (!is_enough_data(pptr, enddata, 2)) |
| 285 | + goto exit; |
269 | 286 | prop->value.integer2 = readInt(pptr); |
270 | 287 | len = 2; |
271 | 288 | break; |
272 | 289 | case MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER: |
| 290 | + if (!is_enough_data(pptr, enddata, 4)) |
| 291 | + goto exit; |
273 | 292 | prop->value.integer4 = readInt4(pptr); |
274 | 293 | len = 4; |
275 | 294 | break; |
276 | 295 | case MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER: |
277 | | - len = MQTTPacket_decodeBuf(*pptr, &prop->value.integer4); |
| 296 | + len = MQTTPacket_decodeBuf(*pptr, enddata, &prop->value.integer4); |
| 297 | + if (len <= 0) |
| 298 | + goto exit; |
278 | 299 | *pptr += len; |
279 | 300 | break; |
280 | 301 | case MQTTPROPERTY_TYPE_BINARY_DATA: |
@@ -308,61 +329,71 @@ int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata) |
308 | 329 | break; |
309 | 330 | } |
310 | 331 | } |
311 | | - return (len == -1) ? -1 : len + 1; /* 1 byte for identifier */ |
| 332 | + exit: |
| 333 | + return (len == -1) ? -1 : len + 1; /* 1 byte for identifier */ |
312 | 334 | } |
313 | 335 |
|
314 | 336 |
|
315 | | -int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata) |
| 337 | +int MQTTProperties_read(MQTTProperties *properties, char **pptr, char *enddata) |
316 | 338 | { |
317 | 339 | int rc = 0; |
318 | | - unsigned int remlength = 0; |
| 340 | + int remlength = 0; |
319 | 341 |
|
320 | 342 | FUNC_ENTRY; |
321 | 343 | /* we assume an initialized properties structure */ |
322 | 344 | if (enddata - (*pptr) > 0) /* enough length to read the VBI? */ |
323 | 345 | { |
324 | 346 | int proplen = 0; |
325 | 347 |
|
326 | | - *pptr += MQTTPacket_decodeBuf(*pptr, &remlength); |
| 348 | + rc = MQTTPacket_decodeBuf(*pptr, enddata, (unsigned int*)&remlength); |
| 349 | + if (rc > 0) |
| 350 | + *pptr += rc; |
| 351 | + else |
| 352 | + { |
| 353 | + rc = MQTTPACKET_BUFFER_TOO_SHORT; |
| 354 | + goto exit; |
| 355 | + } |
327 | 356 | properties->length = remlength; |
328 | 357 | while (remlength > 0) |
329 | 358 | { |
330 | 359 | if (properties->count == properties->max_count) |
331 | 360 | { |
332 | | - properties->max_count += 10; |
333 | | - if (properties->max_count == 10) |
334 | | - properties->array = malloc(sizeof(MQTTProperty) * properties->max_count); |
335 | | - else |
336 | | - { |
337 | | - void* newPtr = realloc(properties->array, sizeof(MQTTProperty) * properties->max_count); |
338 | | - if (newPtr == NULL) |
339 | | - { |
340 | | - free(properties->array); |
341 | | - properties->array = NULL; |
342 | | - } |
| 361 | + properties->max_count += 10; |
| 362 | + if (properties->max_count == 10) |
| 363 | + properties->array = malloc(sizeof(MQTTProperty) * properties->max_count); |
343 | 364 | else |
344 | 365 | { |
345 | | - properties->array = newPtr; |
| 366 | + void *newPtr = realloc(properties->array, sizeof(MQTTProperty) * properties->max_count); |
| 367 | + if (newPtr == NULL) |
| 368 | + { |
| 369 | + free(properties->array); |
| 370 | + properties->array = NULL; |
| 371 | + } else |
| 372 | + { |
| 373 | + properties->array = newPtr; |
| 374 | + } |
346 | 375 | } |
347 | 376 | } |
348 | | - } |
349 | 377 | if (properties->array == NULL) |
350 | 378 | { |
351 | | - rc = PAHO_MEMORY_ERROR; |
| 379 | + rc = PAHO_MEMORY_ERROR; |
352 | 380 | goto exit; |
353 | 381 | } |
354 | 382 | if ((proplen = MQTTProperty_read(&properties->array[properties->count], pptr, enddata)) > 0) |
355 | | - remlength -= proplen; |
| 383 | + remlength -= proplen; |
356 | 384 | else |
357 | | - break; |
| 385 | + { |
| 386 | + rc = MQTTPACKET_BAD; |
| 387 | + break; |
| 388 | + } |
358 | 389 | properties->count++; |
359 | 390 | } |
360 | 391 | if (remlength == 0) |
361 | | - rc = 1; /* data read successfully */ |
| 392 | + rc = 1; /* data read successfully */ |
362 | 393 | } |
363 | 394 |
|
364 | 395 | if (rc != 1 && properties->array != NULL) |
365 | | - MQTTProperties_free(properties); |
| 396 | + MQTTProperties_free(properties); |
366 | 397 |
|
367 | 398 | exit: |
368 | 399 | FUNC_EXIT_RC(rc); |
|
0 commit comments