Fix V5 properties reading of incorrect packets

This commit is contained in:
Ian Craggs 2026-07-06 16:41:37 +01:00
parent f74ecbc171
commit a5aee429c7
No known key found for this signature in database
GPG Key ID: A7AE1A8F2CCAB186
3 changed files with 70 additions and 34 deletions

View File

@ -1059,7 +1059,7 @@ int MQTTPacket_VBIlen(int rem_len)
* @param value the decoded length returned
* @return the number of bytes read from the socket
*/
int MQTTPacket_VBIdecode(int (*getcharfn)(char*, int), unsigned int* value)
int MQTTPacket_VBIdecode(int (*getcharfn)(char*, char*), char* enddata, unsigned int* value)
{
char c;
int multiplier = 1;
@ -1073,12 +1073,15 @@ int MQTTPacket_VBIdecode(int (*getcharfn)(char*, int), unsigned int* value)
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
{
rc = MQTTPACKET_READ_ERROR; /* bad data */
len = MQTTPACKET_READ_ERROR; /* bad data */
goto exit;
}
rc = (*getcharfn)(&c, 1);
rc = (*getcharfn)(&c, enddata);
if (rc != 1)
{
len = MQTTPACKET_READ_ERROR; /* bad data */
goto exit;
}
*value += (c & 127) * multiplier;
multiplier *= 128;
} while ((c & 128) != 0);
@ -1089,19 +1092,21 @@ exit:
static char* bufptr;
int bufchar(char* c, int count)
int bufchar(char* c, char* enddata)
{
int i;
int rc = 1;
for (i = 0; i < count; ++i)
if (enddata - bufptr > 0)
*c = *bufptr++;
return count;
else
rc = -1;
return rc; /* 1 is good, any other value is an error */
}
int MQTTPacket_decodeBuf(char* buf, unsigned int* value)
int MQTTPacket_decodeBuf(char* buf, char* enddata, unsigned int* value)
{
bufptr = buf;
return MQTTPacket_VBIdecode(bufchar, value);
return MQTTPacket_VBIdecode(bufchar, enddata, value);
}

View File

@ -263,7 +263,7 @@ unsigned int readInt4(char** pptr);
void writeMQTTLenString(char** pptr, MQTTLenString lenstring);
int MQTTLenStringRead(MQTTLenString* lenstring, char** pptr, char* enddata);
int MQTTPacket_VBIlen(int rem_len);
int MQTTPacket_decodeBuf(char* buf, unsigned int* value);
int MQTTPacket_decodeBuf(char* buf, char* enddata, unsigned int* value);
#include "MQTTPacketOut.h"

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 IBM Corp. and others
* Copyright (c) 2017, 2026 IBM Corp. and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
@ -248,6 +248,17 @@ int MQTTProperties_write(char** pptr, const MQTTProperties* properties)
return rc;
}
/**
* Is there enough data remaining to read the supplied number of bytes
* @param pptr current read position
* @param enddata pointer to the last byte of the buffer
* @param len number of bytes to be read
* @return 1 if the data can be read, 0 if the buffer is too short
*/
static int is_enough_data(char** pptr, char* enddata, int len)
{
return (enddata - (*pptr)) >= len;
}
int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata)
{
@ -255,6 +266,8 @@ int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata)
len = -1;
memset(prop, 0, sizeof(MQTTProperty));
if (!is_enough_data(pptr, enddata, 1))
goto exit;
prop->identifier = readChar(pptr);
type = MQTTProperty_getType(prop->identifier);
if (type >= MQTTPROPERTY_TYPE_BYTE && type <= MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR)
@ -262,19 +275,27 @@ int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata)
switch (type)
{
case MQTTPROPERTY_TYPE_BYTE:
if (!is_enough_data(pptr, enddata, 1))
goto exit;
prop->value.byte = readChar(pptr);
len = 1;
break;
case MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER:
if (!is_enough_data(pptr, enddata, 2))
goto exit;
prop->value.integer2 = readInt(pptr);
len = 2;
break;
case MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER:
if (!is_enough_data(pptr, enddata, 4))
goto exit;
prop->value.integer4 = readInt4(pptr);
len = 4;
break;
case MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER:
len = MQTTPacket_decodeBuf(*pptr, &prop->value.integer4);
len = MQTTPacket_decodeBuf(*pptr, enddata, &prop->value.integer4);
if (len <= 0)
goto exit;
*pptr += len;
break;
case MQTTPROPERTY_TYPE_BINARY_DATA:
@ -308,14 +329,15 @@ int MQTTProperty_read(MQTTProperty* prop, char** pptr, char* enddata)
break;
}
}
return (len == -1) ? -1 : len + 1; /* 1 byte for identifier */
exit:
return (len == -1) ? -1 : len + 1; /* 1 byte for identifier */
}
int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata)
int MQTTProperties_read(MQTTProperties *properties, char **pptr, char *enddata)
{
int rc = 0;
unsigned int remlength = 0;
int remlength = 0;
FUNC_ENTRY;
/* we assume an initialized properties structure */
@ -323,46 +345,55 @@ int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata)
{
int proplen = 0;
*pptr += MQTTPacket_decodeBuf(*pptr, &remlength);
rc = MQTTPacket_decodeBuf(*pptr, enddata, (unsigned int*)&remlength);
if (rc > 0)
*pptr += rc;
else
{
rc = MQTTPACKET_BUFFER_TOO_SHORT;
goto exit;
}
properties->length = remlength;
while (remlength > 0)
{
if (properties->count == properties->max_count)
{
properties->max_count += 10;
if (properties->max_count == 10)
properties->array = malloc(sizeof(MQTTProperty) * properties->max_count);
else
{
void* newPtr = realloc(properties->array, sizeof(MQTTProperty) * properties->max_count);
if (newPtr == NULL)
{
free(properties->array);
properties->array = NULL;
}
properties->max_count += 10;
if (properties->max_count == 10)
properties->array = malloc(sizeof(MQTTProperty) * properties->max_count);
else
{
properties->array = newPtr;
void *newPtr = realloc(properties->array, sizeof(MQTTProperty) * properties->max_count);
if (newPtr == NULL)
{
free(properties->array);
properties->array = NULL;
} else
{
properties->array = newPtr;
}
}
}
}
if (properties->array == NULL)
{
rc = PAHO_MEMORY_ERROR;
rc = PAHO_MEMORY_ERROR;
goto exit;
}
if ((proplen = MQTTProperty_read(&properties->array[properties->count], pptr, enddata)) > 0)
remlength -= proplen;
remlength -= proplen;
else
break;
{
rc = MQTTPACKET_BAD;
break;
}
properties->count++;
}
if (remlength == 0)
rc = 1; /* data read successfully */
rc = 1; /* data read successfully */
}
if (rc != 1 && properties->array != NULL)
MQTTProperties_free(properties);
MQTTProperties_free(properties);
exit:
FUNC_EXIT_RC(rc);