Improve data parsing
- add length defines for variable data header and fixed data - add size check for fixed data - avoid problems with memory alignment / padding in mbus structures (improve portability) - abort parsing if there are too many DIFE or VIFEs - check for premature end of variable data - check size of variable length VIF
This commit is contained in:
parent
3381d1b41d
commit
dd56a08811
@ -2649,8 +2649,29 @@ mbus_data_fixed_parse(mbus_frame *frame, mbus_data_fixed *data)
|
||||
{
|
||||
if (frame && data)
|
||||
{
|
||||
// copy the fixed-length data structure
|
||||
memcpy((void *)data, (void *)(frame->data), sizeof(mbus_data_fixed));
|
||||
if (frame->data_size != MBUS_DATA_FIXED_LENGTH)
|
||||
{
|
||||
snprintf(error_str, sizeof(error_str), "Invalid length for fixed data.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// copy the fixed-length data structure bytewise
|
||||
data->id_bcd[0] = frame->data[0];
|
||||
data->id_bcd[1] = frame->data[1];
|
||||
data->id_bcd[2] = frame->data[2];
|
||||
data->id_bcd[3] = frame->data[3];
|
||||
data->tx_cnt = frame->data[4];
|
||||
data->status = frame->data[5];
|
||||
data->cnt1_type = frame->data[6];
|
||||
data->cnt2_type = frame->data[7];
|
||||
data->cnt1_val[0] = frame->data[8];
|
||||
data->cnt1_val[1] = frame->data[9];
|
||||
data->cnt1_val[2] = frame->data[10];
|
||||
data->cnt1_val[3] = frame->data[11];
|
||||
data->cnt2_val[0] = frame->data[12];
|
||||
data->cnt2_val[1] = frame->data[13];
|
||||
data->cnt2_val[2] = frame->data[14];
|
||||
data->cnt2_val[3] = frame->data[15];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2673,12 +2694,27 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
// parse header
|
||||
data->nrecords = 0;
|
||||
data->more_records_follow = 0;
|
||||
i = sizeof(mbus_data_variable_header);
|
||||
if(frame->data_size < i)
|
||||
return -1;
|
||||
i = MBUS_DATA_VARIABLE_HEADER_LENGTH;
|
||||
|
||||
// first copy the variable data fixed header
|
||||
memcpy((void *)&(data->header), (void *)(frame->data), i);
|
||||
if(frame->data_size < i)
|
||||
{
|
||||
snprintf(error_str, sizeof(error_str), "Variable header too short.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// first copy the variable data fixed header bytewise
|
||||
data->header.id_bcd[0] = frame->data[0];
|
||||
data->header.id_bcd[1] = frame->data[1];
|
||||
data->header.id_bcd[2] = frame->data[2];
|
||||
data->header.id_bcd[3] = frame->data[3];
|
||||
data->header.manufacturer[0] = frame->data[4];
|
||||
data->header.manufacturer[1] = frame->data[5];
|
||||
data->header.version = frame->data[6];
|
||||
data->header.medium = frame->data[7];
|
||||
data->header.access_no = frame->data[8];
|
||||
data->header.status = frame->data[9];
|
||||
data->header.signature[0] = frame->data[10];
|
||||
data->header.signature[1] = frame->data[11];
|
||||
|
||||
data->record = NULL;
|
||||
|
||||
@ -2732,10 +2768,19 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
|
||||
// read DIF extensions
|
||||
record->drh.dib.ndife = 0;
|
||||
while (frame->data[i] & MBUS_DIB_DIF_EXTENSION_BIT &&
|
||||
record->drh.dib.ndife < NITEMS(record->drh.dib.dife))
|
||||
while ((i < frame->data_size) &&
|
||||
(frame->data[i] & MBUS_DIB_DIF_EXTENSION_BIT))
|
||||
{
|
||||
unsigned char dife = frame->data[i+1];
|
||||
unsigned char dife;
|
||||
|
||||
if (record->drh.dib.ndife >= NITEMS(record->drh.dib.dife))
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Too many DIFE.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dife = frame->data[i+1];
|
||||
record->drh.dib.dife[record->drh.dib.ndife] = dife;
|
||||
|
||||
record->drh.dib.ndife++;
|
||||
@ -2743,6 +2788,13 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
}
|
||||
i++;
|
||||
|
||||
if (i > frame->data_size)
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Premature end of record at DIF.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// read and parse VIB (= VIF + VIFE)
|
||||
|
||||
// VIF
|
||||
@ -2753,9 +2805,17 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
// variable length VIF in ASCII format
|
||||
int var_vif_len;
|
||||
var_vif_len = frame->data[i++];
|
||||
if (var_vif_len > sizeof(record->drh.vib.custom_vif))
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Too long variable length VIF.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i + var_vif_len > frame->data_size)
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Premature end of record at variable length VIF.");
|
||||
return -1;
|
||||
}
|
||||
mbus_data_str_decode(record->drh.vib.custom_vif, &(frame->data[i]), var_vif_len);
|
||||
@ -2770,10 +2830,19 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
record->drh.vib.vife[0] = frame->data[i];
|
||||
record->drh.vib.nvife++;
|
||||
|
||||
while (frame->data[i] & MBUS_DIB_VIF_EXTENSION_BIT &&
|
||||
record->drh.vib.nvife < NITEMS(record->drh.vib.vife))
|
||||
while ((i < frame->data_size) &&
|
||||
(frame->data[i] & MBUS_DIB_VIF_EXTENSION_BIT))
|
||||
{
|
||||
unsigned char vife = frame->data[i+1];
|
||||
unsigned char vife;
|
||||
|
||||
if (record->drh.vib.nvife < NITEMS(record->drh.vib.vife))
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Too many VIFE.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vife = frame->data[i+1];
|
||||
record->drh.vib.vife[record->drh.vib.nvife] = vife;
|
||||
|
||||
record->drh.vib.nvife++;
|
||||
@ -2782,6 +2851,13 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > frame->data_size)
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Premature end of record at VIF.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// re-calculate data length, if of variable length type
|
||||
if ((record->drh.dib.dif & 0x0F) == 0x0D) // flag for variable length data
|
||||
{
|
||||
@ -2797,6 +2873,13 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
|
||||
record->data_len = frame->data[i++] - 0xF0;
|
||||
}
|
||||
|
||||
if (i + record->data_len > frame->data_size)
|
||||
{
|
||||
mbus_data_record_free(record);
|
||||
snprintf(error_str, sizeof(error_str), "Premature end of record at data.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// copy data
|
||||
for (j = 0; j < record->data_len; j++)
|
||||
{
|
||||
|
@ -192,6 +192,8 @@ typedef struct _mbus_data_variable_header {
|
||||
|
||||
} mbus_data_variable_header;
|
||||
|
||||
#define MBUS_DATA_VARIABLE_HEADER_LENGTH 12
|
||||
|
||||
//
|
||||
// VARIABLE LENGTH DATA FORMAT
|
||||
//
|
||||
@ -241,6 +243,8 @@ typedef struct _mbus_data_fixed {
|
||||
|
||||
} mbus_data_fixed;
|
||||
|
||||
#define MBUS_DATA_FIXED_LENGTH 16
|
||||
|
||||
//
|
||||
// ABSTRACT DATA FORMAT (error, fixed or variable length)
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user