dnp3: allocate variable-length object fields dynamically

Introduce a new code generated type, dynchararray. Use this new
dynamically allocated char array instead of using a 65535 static array.

Ticket: #8827
pull/16213/head
Jason Ish 2 months ago committed by Victor Julien
parent 99942aa50d
commit 172204be61

@ -85,7 +85,7 @@ void DNP3PushPoint(lua_State *luastate, DNP3Object *object,
lua_pushliteral(luastate, "{{field.name}}");
lua_pushnumber(luastate, data->{{field.name}});
lua_settable(luastate, -3);
{% elif field["type"] == "chararray" %}
{% elif field["type"] in ["chararray", "dynchararray"] %}
lua_pushliteral(luastate, "{{field.name}}");
LuaPushStringBuffer(luastate, (uint8_t *)data->{{field.name}},
strlen(data->{{field.name}}));
@ -169,7 +169,7 @@ void OutputJsonDNP3SetItem(SCJsonBuilder *js, DNP3Object *object,
SCJbSetBase64(js, "data->{{field.name}}", data->{{field.name}}, data->{{field.len_field}});
{% elif field.type == "vstr4" %}
SCJbSetString(js, "data->{{field.name}}", data->{{field.name}});
{% elif field.type == "chararray" %}
{% elif field.type in ["chararray", "dynchararray"] %}
if (data->{{field.len_field}} > 0) {
SCJbSetStringFromBytes(
js, "{{field.name}}", (const uint8_t *)data->{{field.name}}, data->{{field.len_field}});
@ -199,11 +199,8 @@ void OutputJsonDNP3SetItem(SCJsonBuilder *js, DNP3Object *object,
"""
def has_freeable_types(fields):
freeable_types = [
"bytearray",
]
for field in fields:
if field["type"] in freeable_types:
if field["type"] in ["bytearray", "dynchararray"]:
return True
return False
@ -284,6 +281,8 @@ typedef struct DNP3ObjectG{{object.group}}V{{object.variation}}_ {
uint64_t {{field.name}};
{% elif field.type == "bytearray" %}
uint8_t *{{field.name}};
{% elif field.type == "dynchararray" %}
char *{{field.name}};
{% elif field.type == "vstr4" %}
char {{field.name}}[5];
{% elif field.type == "chararray" %}
@ -505,12 +504,36 @@ static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t
*buf += object->{{field.len_field}};
*len -= object->{{field.len_field}};
}
{% elif field.type == "dynchararray" %}
{% if field.len_from_prefix %}
if (prefix - (offset - *len) >= {{field.size}} || prefix < (offset - *len)) {
goto error;
}
{% if field.size <= 256 %}
object->{{field.len_field}} = (uint8_t)(prefix - (offset - *len));
{% else %}
object->{{field.len_field}} = (uint16_t)(prefix - (offset - *len));
{% endif %}
{% endif %}
if (*len < object->{{field.len_field}}) {
goto error;
}
object->{{field.name}} = SCMalloc((size_t)object->{{field.len_field}} + 1);
if (unlikely(object->{{field.name}} == NULL)) {
goto error;
}
if (object->{{field.len_field}} > 0) {
memcpy(object->{{field.name}}, *buf, object->{{field.len_field}});
}
object->{{field.name}}[object->{{field.len_field}}] = '\\\\0';
*buf += object->{{field.len_field}};
*len -= object->{{field.len_field}};
{% elif field.type == "chararray" %}
{% if field.len_from_prefix %}
if (prefix - (offset - *len) >= {{field.size}} || prefix < (offset - *len)) {
goto error;
}
{% if field.size == 255 %}
{% if field.size <= 256 %}
object->{{field.len_field}} = (uint8_t)(prefix - (offset - *len));
{% else %}
object->{{field.len_field}} = (uint16_t)(prefix - (offset - *len));
@ -566,7 +589,7 @@ static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t
error:
if (object != NULL) {
{% for field in object.fields %}
{% if field.type == "bytearray" %}
{% if field.type in ["bytearray", "dynchararray"] %}
if (object->{{field.name}} != NULL) {
SCFree(object->{{field.name}});
}
@ -589,7 +612,7 @@ void DNP3FreeObjectPoint(int group, int variation, void *point)
case DNP3_OBJECT_CODE({{object.group}}, {{object.variation}}): {
DNP3ObjectG{{object.group}}V{{object.variation}} *object = (DNP3ObjectG{{object.group}}V{{object.variation}} *)point;
{% for field in object.fields %}
{% if field.type == "bytearray" %}
{% if field.type in ["bytearray", "dynchararray"] %}
if (object->{{field.name}} != NULL) {
SCFree(object->{{field.name}});
}

@ -2341,13 +2341,13 @@ objects:
name: file_function_code
- type: uint8
name: status_code
- type: chararray
- type: dynchararray
name: filename
size: 65536
len_field: filename_size
- type: uint16
name: data_size
- type: chararray
- type: dynchararray
name: data
size: 65536
len_field: data_size
@ -2365,11 +2365,11 @@ objects:
name: password_size
- type: uint32
name: authentication_key
- type: chararray
- type: dynchararray
name: username
size: 65536
len_field: username_size
- type: chararray
- type: dynchararray
name: password
size: 65536
len_field: password_size
@ -2396,7 +2396,7 @@ objects:
name: maximum_block_size
- type: uint16
name: request_id
- type: chararray
- type: dynchararray
name: filename
size: 65536
len_field: filename_size
@ -2484,7 +2484,7 @@ objects:
name: permissions
- type: uint16
name: request_id
- type: chararray
- type: dynchararray
name: filename
size: 65536
len_field: filename_size
@ -2498,7 +2498,7 @@ objects:
- type: uint16
name: file_specification_len
fields:
- type: chararray
- type: dynchararray
name: file_specification
size: 65536
len_from_prefix: true
@ -2762,7 +2762,7 @@ objects:
name: error_code
- type: dnp3time
name: time_of_error
- type: chararray
- type: dynchararray
name: error_text
size: 65536
len_from_prefix: true
@ -2820,7 +2820,7 @@ objects:
name: user_public_key_len
- type: uint16
name: certification_data_len
- type: chararray
- type: dynchararray
name: username
size: 65536
len_field: username_len
@ -2843,7 +2843,7 @@ objects:
name: username_len
- type: uint16
name: master_challenge_data_len
- type: chararray
- type: dynchararray
size: 65536
name: username
len_field: username_len

@ -6793,29 +6793,35 @@ static int DNP3DecodeObjectG70V1(const uint8_t **buf, uint16_t *len, uint8_t pre
if (!DNP3ReadUint8(buf, len, &object->status_code)) {
goto error;
}
if (*len < object->filename_size) {
goto error;
}
object->filename = SCMalloc((size_t)object->filename_size + 1);
if (unlikely(object->filename == NULL)) {
goto error;
}
if (object->filename_size > 0) {
if (*len < object->filename_size) {
/* Not enough data. */
goto error;
}
memcpy(object->filename, *buf, object->filename_size);
*buf += object->filename_size;
*len -= object->filename_size;
}
object->filename[object->filename_size] = '\0';
*buf += object->filename_size;
*len -= object->filename_size;
if (!DNP3ReadUint16(buf, len, &object->data_size)) {
goto error;
}
if (*len < object->data_size) {
goto error;
}
object->data = SCMalloc((size_t)object->data_size + 1);
if (unlikely(object->data == NULL)) {
goto error;
}
if (object->data_size > 0) {
if (*len < object->data_size) {
/* Not enough data. */
goto error;
}
memcpy(object->data, *buf, object->data_size);
*buf += object->data_size;
*len -= object->data_size;
}
object->data[object->data_size] = '\0';
*buf += object->data_size;
*len -= object->data_size;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -6828,6 +6834,12 @@ static int DNP3DecodeObjectG70V1(const uint8_t **buf, uint16_t *len, uint8_t pre
return 1;
error:
if (object != NULL) {
if (object->filename != NULL) {
SCFree(object->filename);
}
if (object->data != NULL) {
SCFree(object->data);
}
SCFree(object);
}
@ -6870,26 +6882,32 @@ static int DNP3DecodeObjectG70V2(const uint8_t **buf, uint16_t *len, uint8_t pre
if (!DNP3ReadUint32(buf, len, &object->authentication_key)) {
goto error;
}
if (*len < object->username_size) {
goto error;
}
object->username = SCMalloc((size_t)object->username_size + 1);
if (unlikely(object->username == NULL)) {
goto error;
}
if (object->username_size > 0) {
if (*len < object->username_size) {
/* Not enough data. */
goto error;
}
memcpy(object->username, *buf, object->username_size);
*buf += object->username_size;
*len -= object->username_size;
}
object->username[object->username_size] = '\0';
*buf += object->username_size;
*len -= object->username_size;
if (*len < object->password_size) {
goto error;
}
object->password = SCMalloc((size_t)object->password_size + 1);
if (unlikely(object->password == NULL)) {
goto error;
}
if (object->password_size > 0) {
if (*len < object->password_size) {
/* Not enough data. */
goto error;
}
memcpy(object->password, *buf, object->password_size);
*buf += object->password_size;
*len -= object->password_size;
}
object->password[object->password_size] = '\0';
*buf += object->password_size;
*len -= object->password_size;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -6902,6 +6920,12 @@ static int DNP3DecodeObjectG70V2(const uint8_t **buf, uint16_t *len, uint8_t pre
return 1;
error:
if (object != NULL) {
if (object->username != NULL) {
SCFree(object->username);
}
if (object->password != NULL) {
SCFree(object->password);
}
SCFree(object);
}
@ -6956,16 +6980,19 @@ static int DNP3DecodeObjectG70V3(const uint8_t **buf, uint16_t *len, uint8_t pre
if (!DNP3ReadUint16(buf, len, &object->request_id)) {
goto error;
}
if (*len < object->filename_size) {
goto error;
}
object->filename = SCMalloc((size_t)object->filename_size + 1);
if (unlikely(object->filename == NULL)) {
goto error;
}
if (object->filename_size > 0) {
if (*len < object->filename_size) {
/* Not enough data. */
goto error;
}
memcpy(object->filename, *buf, object->filename_size);
*buf += object->filename_size;
*len -= object->filename_size;
}
object->filename[object->filename_size] = '\0';
*buf += object->filename_size;
*len -= object->filename_size;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -6978,6 +7005,9 @@ static int DNP3DecodeObjectG70V3(const uint8_t **buf, uint16_t *len, uint8_t pre
return 1;
error:
if (object != NULL) {
if (object->filename != NULL) {
SCFree(object->filename);
}
SCFree(object);
}
@ -7030,7 +7060,7 @@ static int DNP3DecodeObjectG70V4(const uint8_t **buf, uint16_t *len, uint8_t pre
if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) {
goto error;
}
object->optional_text_len = (uint16_t)(prefix - (offset - *len));
object->optional_text_len = (uint8_t)(prefix - (offset - *len));
if (object->optional_text_len > 0) {
if (*len < object->optional_text_len) {
/* Not enough data. */
@ -7096,7 +7126,7 @@ static int DNP3DecodeObjectG70V5(const uint8_t **buf, uint16_t *len, uint8_t pre
if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) {
goto error;
}
object->file_data_len = (uint16_t)(prefix - (offset - *len));
object->file_data_len = (uint8_t)(prefix - (offset - *len));
if (object->file_data_len > 0) {
if (*len < object->file_data_len) {
/* Not enough data. */
@ -7165,7 +7195,7 @@ static int DNP3DecodeObjectG70V6(const uint8_t **buf, uint16_t *len, uint8_t pre
if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) {
goto error;
}
object->optional_text_len = (uint16_t)(prefix - (offset - *len));
object->optional_text_len = (uint8_t)(prefix - (offset - *len));
if (object->optional_text_len > 0) {
if (*len < object->optional_text_len) {
/* Not enough data. */
@ -7236,16 +7266,19 @@ static int DNP3DecodeObjectG70V7(const uint8_t **buf, uint16_t *len, uint8_t pre
if (!DNP3ReadUint16(buf, len, &object->request_id)) {
goto error;
}
if (*len < object->filename_size) {
goto error;
}
object->filename = SCMalloc((size_t)object->filename_size + 1);
if (unlikely(object->filename == NULL)) {
goto error;
}
if (object->filename_size > 0) {
if (*len < object->filename_size) {
/* Not enough data. */
goto error;
}
memcpy(object->filename, *buf, object->filename_size);
*buf += object->filename_size;
*len -= object->filename_size;
}
object->filename[object->filename_size] = '\0';
*buf += object->filename_size;
*len -= object->filename_size;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -7258,6 +7291,9 @@ static int DNP3DecodeObjectG70V7(const uint8_t **buf, uint16_t *len, uint8_t pre
return 1;
error:
if (object != NULL) {
if (object->filename != NULL) {
SCFree(object->filename);
}
SCFree(object);
}
@ -7296,16 +7332,19 @@ static int DNP3DecodeObjectG70V8(const uint8_t **buf, uint16_t *len, uint8_t pre
goto error;
}
object->file_specification_len = (uint16_t)(prefix - (offset - *len));
if (*len < object->file_specification_len) {
goto error;
}
object->file_specification = SCMalloc((size_t)object->file_specification_len + 1);
if (unlikely(object->file_specification == NULL)) {
goto error;
}
if (object->file_specification_len > 0) {
if (*len < object->file_specification_len) {
/* Not enough data. */
goto error;
}
memcpy(object->file_specification, *buf, object->file_specification_len);
*buf += object->file_specification_len;
*len -= object->file_specification_len;
}
object->file_specification[object->file_specification_len] = '\0';
*buf += object->file_specification_len;
*len -= object->file_specification_len;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -7318,6 +7357,9 @@ static int DNP3DecodeObjectG70V8(const uint8_t **buf, uint16_t *len, uint8_t pre
return 1;
error:
if (object != NULL) {
if (object->file_specification != NULL) {
SCFree(object->file_specification);
}
SCFree(object);
}
@ -8044,16 +8086,19 @@ static int DNP3DecodeObjectG120V7(const uint8_t **buf, uint16_t *len, uint8_t pr
goto error;
}
object->error_text_len = (uint16_t)(prefix - (offset - *len));
if (*len < object->error_text_len) {
goto error;
}
object->error_text = SCMalloc((size_t)object->error_text_len + 1);
if (unlikely(object->error_text == NULL)) {
goto error;
}
if (object->error_text_len > 0) {
if (*len < object->error_text_len) {
/* Not enough data. */
goto error;
}
memcpy(object->error_text, *buf, object->error_text_len);
*buf += object->error_text_len;
*len -= object->error_text_len;
}
object->error_text[object->error_text_len] = '\0';
*buf += object->error_text_len;
*len -= object->error_text_len;
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
goto error;
@ -8066,6 +8111,9 @@ static int DNP3DecodeObjectG120V7(const uint8_t **buf, uint16_t *len, uint8_t pr
return 1;
error:
if (object != NULL) {
if (object->error_text != NULL) {
SCFree(object->error_text);
}
SCFree(object);
}
@ -8255,16 +8303,19 @@ static int DNP3DecodeObjectG120V10(const uint8_t **buf, uint16_t *len, uint8_t p
if (!DNP3ReadUint16(buf, len, &object->certification_data_len)) {
goto error;
}
if (*len < object->username_len) {
goto error;
}
object->username = SCMalloc((size_t)object->username_len + 1);
if (unlikely(object->username == NULL)) {
goto error;
}
if (object->username_len > 0) {
if (*len < object->username_len) {
/* Not enough data. */
goto error;
}
memcpy(object->username, *buf, object->username_len);
*buf += object->username_len;
*len -= object->username_len;
}
object->username[object->username_len] = '\0';
*buf += object->username_len;
*len -= object->username_len;
if (object->user_public_key_len > 0) {
if (*len < object->user_public_key_len) {
/* Not enough data. */
@ -8303,6 +8354,9 @@ static int DNP3DecodeObjectG120V10(const uint8_t **buf, uint16_t *len, uint8_t p
return 1;
error:
if (object != NULL) {
if (object->username != NULL) {
SCFree(object->username);
}
if (object->user_public_key != NULL) {
SCFree(object->user_public_key);
}
@ -8349,16 +8403,19 @@ static int DNP3DecodeObjectG120V11(const uint8_t **buf, uint16_t *len, uint8_t p
if (!DNP3ReadUint16(buf, len, &object->master_challenge_data_len)) {
goto error;
}
if (*len < object->username_len) {
goto error;
}
object->username = SCMalloc((size_t)object->username_len + 1);
if (unlikely(object->username == NULL)) {
goto error;
}
if (object->username_len > 0) {
if (*len < object->username_len) {
/* Not enough data. */
goto error;
}
memcpy(object->username, *buf, object->username_len);
*buf += object->username_len;
*len -= object->username_len;
}
object->username[object->username_len] = '\0';
*buf += object->username_len;
*len -= object->username_len;
if (object->master_challenge_data_len > 0) {
if (*len < object->master_challenge_data_len) {
/* Not enough data. */
@ -8384,6 +8441,9 @@ static int DNP3DecodeObjectG120V11(const uint8_t **buf, uint16_t *len, uint8_t p
return 1;
error:
if (object != NULL) {
if (object->username != NULL) {
SCFree(object->username);
}
if (object->master_challenge_data != NULL) {
SCFree(object->master_challenge_data);
}
@ -8845,6 +8905,47 @@ error:
void DNP3FreeObjectPoint(int group, int variation, void *point)
{
switch(DNP3_OBJECT_CODE(group, variation)) {
case DNP3_OBJECT_CODE(70, 1): {
DNP3ObjectG70V1 *object = (DNP3ObjectG70V1 *)point;
if (object->filename != NULL) {
SCFree(object->filename);
}
if (object->data != NULL) {
SCFree(object->data);
}
break;
}
case DNP3_OBJECT_CODE(70, 2): {
DNP3ObjectG70V2 *object = (DNP3ObjectG70V2 *)point;
if (object->username != NULL) {
SCFree(object->username);
}
if (object->password != NULL) {
SCFree(object->password);
}
break;
}
case DNP3_OBJECT_CODE(70, 3): {
DNP3ObjectG70V3 *object = (DNP3ObjectG70V3 *)point;
if (object->filename != NULL) {
SCFree(object->filename);
}
break;
}
case DNP3_OBJECT_CODE(70, 7): {
DNP3ObjectG70V7 *object = (DNP3ObjectG70V7 *)point;
if (object->filename != NULL) {
SCFree(object->filename);
}
break;
}
case DNP3_OBJECT_CODE(70, 8): {
DNP3ObjectG70V8 *object = (DNP3ObjectG70V8 *)point;
if (object->file_specification != NULL) {
SCFree(object->file_specification);
}
break;
}
case DNP3_OBJECT_CODE(83, 1): {
DNP3ObjectG83V1 *object = (DNP3ObjectG83V1 *)point;
if (object->data_objects != NULL) {
@ -8883,6 +8984,13 @@ void DNP3FreeObjectPoint(int group, int variation, void *point)
}
break;
}
case DNP3_OBJECT_CODE(120, 7): {
DNP3ObjectG120V7 *object = (DNP3ObjectG120V7 *)point;
if (object->error_text != NULL) {
SCFree(object->error_text);
}
break;
}
case DNP3_OBJECT_CODE(120, 8): {
DNP3ObjectG120V8 *object = (DNP3ObjectG120V8 *)point;
if (object->certificate != NULL) {
@ -8899,6 +9007,9 @@ void DNP3FreeObjectPoint(int group, int variation, void *point)
}
case DNP3_OBJECT_CODE(120, 10): {
DNP3ObjectG120V10 *object = (DNP3ObjectG120V10 *)point;
if (object->username != NULL) {
SCFree(object->username);
}
if (object->user_public_key != NULL) {
SCFree(object->user_public_key);
}
@ -8909,6 +9020,9 @@ void DNP3FreeObjectPoint(int group, int variation, void *point)
}
case DNP3_OBJECT_CODE(120, 11): {
DNP3ObjectG120V11 *object = (DNP3ObjectG120V11 *)point;
if (object->username != NULL) {
SCFree(object->username);
}
if (object->master_challenge_data != NULL) {
SCFree(object->master_challenge_data);
}

@ -1199,9 +1199,9 @@ typedef struct DNP3ObjectG70V1_ {
uint32_t group_id;
uint8_t file_function_code;
uint8_t status_code;
char filename[65536];
char *filename;
uint16_t data_size;
char data[65536];
char *data;
} DNP3ObjectG70V1;
typedef struct DNP3ObjectG70V2_ {
@ -1210,8 +1210,8 @@ typedef struct DNP3ObjectG70V2_ {
uint16_t password_offset;
uint16_t password_size;
uint32_t authentication_key;
char username[65536];
char password[65536];
char *username;
char *password;
} DNP3ObjectG70V2;
typedef struct DNP3ObjectG70V3_ {
@ -1224,7 +1224,7 @@ typedef struct DNP3ObjectG70V3_ {
uint16_t operational_mode;
uint16_t maximum_block_size;
uint16_t request_id;
char filename[65536];
char *filename;
} DNP3ObjectG70V3;
typedef struct DNP3ObjectG70V4_ {
@ -1260,11 +1260,11 @@ typedef struct DNP3ObjectG70V7_ {
uint64_t created_timestamp;
uint16_t permissions;
uint16_t request_id;
char filename[65536];
char *filename;
} DNP3ObjectG70V7;
typedef struct DNP3ObjectG70V8_ {
char file_specification[65536];
char *file_specification;
uint16_t file_specification_len;
} DNP3ObjectG70V8;
@ -1351,7 +1351,7 @@ typedef struct DNP3ObjectG120V7_ {
uint16_t association_id;
uint8_t error_code;
uint64_t time_of_error;
char error_text[65536];
char *error_text;
uint16_t error_text_len;
} DNP3ObjectG120V7;
@ -1376,7 +1376,7 @@ typedef struct DNP3ObjectG120V10_ {
uint16_t username_len;
uint16_t user_public_key_len;
uint16_t certification_data_len;
char username[65536];
char *username;
uint8_t *user_public_key;
uint8_t *certification_data;
} DNP3ObjectG120V10;
@ -1385,7 +1385,7 @@ typedef struct DNP3ObjectG120V11_ {
uint8_t key_change_method;
uint16_t username_len;
uint16_t master_challenge_data_len;
char username[65536];
char *username;
uint8_t *master_challenge_data;
} DNP3ObjectG120V11;

@ -2546,6 +2546,111 @@ static int DNP3ParserTestParsePDU01(void)
PASS;
}
/**
* \test Ensure variable-length DNP3 objects do not embed maximum-sized buffers.
*/
static int DNP3ParserObjectStructSizeTest(void)
{
const size_t max_point_size = 1024;
FAIL_IF(sizeof(DNP3ObjectG70V1) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG70V2) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG70V3) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG70V7) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG70V8) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG120V7) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG120V10) >= max_point_size);
FAIL_IF(sizeof(DNP3ObjectG120V11) >= max_point_size);
PASS;
}
/**
* \test Decode non-empty dynamically allocated G70V2 strings.
*/
static int DNP3ParserDecodeG70V2Test(void)
{
const uint8_t input[] = {
0x00,
0x00,
0x03,
0x00,
0x00,
0x00,
0x06,
0x00,
0x78,
0x56,
0x34,
0x12,
'b',
'o',
'b',
's',
'e',
'c',
'r',
'e',
't',
};
const uint8_t *buf = input;
uint16_t len = sizeof(input);
DNP3PointList *points = DNP3PointListAlloc();
FAIL_IF_NULL(points);
int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
FAIL_IF(event != 0);
FAIL_IF(len != 0);
DNP3Point *point = TAILQ_FIRST(points);
FAIL_IF_NULL(point);
DNP3ObjectG70V2 *data = point->data;
FAIL_IF_NULL(data);
FAIL_IF(strcmp(data->username, "bob") != 0);
FAIL_IF(strcmp(data->password, "secret") != 0);
FAIL_IF(data->authentication_key != 0x12345678);
DNP3FreeObjectPointList(70, 2, points);
PASS;
}
/**
* \test Clean up an allocated G70V2 username when the password is truncated.
*/
static int DNP3ParserDecodeG70V2TruncatedTest(void)
{
const uint8_t input[] = {
0x00,
0x00,
0x03,
0x00,
0x00,
0x00,
0x06,
0x00,
0x78,
0x56,
0x34,
0x12,
'b',
'o',
'b',
's',
'e',
'c',
};
const uint8_t *buf = input;
uint16_t len = sizeof(input);
DNP3PointList *points = DNP3PointListAlloc();
FAIL_IF_NULL(points);
int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
FAIL_IF(event != DNP3_DECODER_EVENT_MALFORMED);
FAIL_IF_NOT(TAILQ_EMPTY(points));
DNP3FreeObjectPointList(70, 2, points);
PASS;
}
/**
* \test Test the decode of a DNP3 fragment with a single 70:3 object.
*/
@ -2694,6 +2799,9 @@ void DNP3ParserRegisterTests(void)
UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
UtRegisterTest("DNP3ParserObjectStructSizeTest", DNP3ParserObjectStructSizeTest);
UtRegisterTest("DNP3ParserDecodeG70V2Test", DNP3ParserDecodeG70V2Test);
UtRegisterTest("DNP3ParserDecodeG70V2TruncatedTest", DNP3ParserDecodeG70V2TruncatedTest);
UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
UtRegisterTest("DNP3ParserUnknownEventAlertTest",
DNP3ParserUnknownEventAlertTest);

Loading…
Cancel
Save