From 38d41e6fa60fc2fdb0fc069a3cb788c989bb8082 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Mon, 6 Apr 2026 20:38:57 +0200 Subject: [PATCH] dnp3: fix off-by-one in array sizes So that we can write a final zero without overflowing the array and relying on padding to avoid further problems Ticket: 8448 --- scripts/dnp3-gen/dnp3-objects.yaml | 26 +++++++++++++------------- src/app-layer-dnp3-objects.c | 10 +++++----- src/app-layer-dnp3-objects.h | 26 +++++++++++++------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/scripts/dnp3-gen/dnp3-objects.yaml b/scripts/dnp3-gen/dnp3-objects.yaml index 529910f78d..7b4ab3677a 100644 --- a/scripts/dnp3-gen/dnp3-objects.yaml +++ b/scripts/dnp3-gen/dnp3-objects.yaml @@ -2343,13 +2343,13 @@ objects: name: status_code - type: chararray name: filename - size: 65535 + size: 65536 len_field: filename_size - type: uint16 name: data_size - type: chararray name: data - size: 65535 + size: 65536 len_field: data_size - group: 70 @@ -2367,11 +2367,11 @@ objects: name: authentication_key - type: chararray name: username - size: 65535 + size: 65536 len_field: username_size - type: chararray name: password - size: 65535 + size: 65536 len_field: password_size - group: 70 @@ -2398,7 +2398,7 @@ objects: name: request_id - type: chararray name: filename - size: 65535 + size: 65536 len_field: filename_size # Checked. @@ -2422,7 +2422,7 @@ objects: name: status_code - type: chararray name: optional_text - size: 0xff + size: 256 len_from_prefix: true len_field: optional_text_len @@ -2441,7 +2441,7 @@ objects: name: block_number # Includes "last" flag. - type: chararray name: file_data - size: 0xff + size: 256 len_from_prefix: true len_field: file_data_len @@ -2462,7 +2462,7 @@ objects: name: status_code - type: chararray name: optional_text - size: 0xff + size: 256 len_from_prefix: true len_field: optional_text_len @@ -2486,7 +2486,7 @@ objects: name: request_id - type: chararray name: filename - size: 0xffff + size: 65536 len_field: filename_size # Checked. @@ -2500,7 +2500,7 @@ objects: fields: - type: chararray name: file_specification - size: 0xffff + size: 65536 len_from_prefix: true len_field: file_specification_len @@ -2764,7 +2764,7 @@ objects: name: time_of_error - type: chararray name: error_text - size: 65535 + size: 65536 len_from_prefix: true len_field: error_text_len @@ -2822,7 +2822,7 @@ objects: name: certification_data_len - type: chararray name: username - size: 65535 + size: 65536 len_field: username_len - type: bytearray name: user_public_key @@ -2844,7 +2844,7 @@ objects: - type: uint16 name: master_challenge_data_len - type: chararray - size: 65535 + size: 65536 name: username len_field: username_len - type: bytearray diff --git a/src/app-layer-dnp3-objects.c b/src/app-layer-dnp3-objects.c index 972118d606..526cbe6ef3 100644 --- a/src/app-layer-dnp3-objects.c +++ b/src/app-layer-dnp3-objects.c @@ -7027,7 +7027,7 @@ static int DNP3DecodeObjectG70V4(const uint8_t **buf, uint16_t *len, uint8_t pre if (!DNP3ReadUint8(buf, len, &object->status_code)) { goto error; } - if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) { + if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) { goto error; } object->optional_text_len = (uint8_t)(prefix - (offset - *len)); @@ -7093,7 +7093,7 @@ static int DNP3DecodeObjectG70V5(const uint8_t **buf, uint16_t *len, uint8_t pre if (!DNP3ReadUint32(buf, len, &object->block_number)) { goto error; } - if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) { + if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) { goto error; } object->file_data_len = (uint8_t)(prefix - (offset - *len)); @@ -7162,7 +7162,7 @@ static int DNP3DecodeObjectG70V6(const uint8_t **buf, uint16_t *len, uint8_t pre if (!DNP3ReadUint8(buf, len, &object->status_code)) { goto error; } - if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) { + if (prefix - (offset - *len) >= 256 || prefix < (offset - *len)) { goto error; } object->optional_text_len = (uint8_t)(prefix - (offset - *len)); @@ -7292,7 +7292,7 @@ static int DNP3DecodeObjectG70V8(const uint8_t **buf, uint16_t *len, uint8_t pre offset = *len; - if (prefix - (offset - *len) >= 65535 || prefix < (offset - *len)) { + if (prefix - (offset - *len) >= 65536 || prefix < (offset - *len)) { goto error; } object->file_specification_len = (uint16_t)(prefix - (offset - *len)); @@ -8040,7 +8040,7 @@ static int DNP3DecodeObjectG120V7(const uint8_t **buf, uint16_t *len, uint8_t pr if (!DNP3ReadUint48(buf, len, &object->time_of_error)) { goto error; } - if (prefix - (offset - *len) >= 65535 || prefix < (offset - *len)) { + if (prefix - (offset - *len) >= 65536 || prefix < (offset - *len)) { goto error; } object->error_text_len = (uint16_t)(prefix - (offset - *len)); diff --git a/src/app-layer-dnp3-objects.h b/src/app-layer-dnp3-objects.h index 6686a2c4c4..39561e6606 100644 --- a/src/app-layer-dnp3-objects.h +++ b/src/app-layer-dnp3-objects.h @@ -1199,9 +1199,9 @@ typedef struct DNP3ObjectG70V1_ { uint32_t group_id; uint8_t file_function_code; uint8_t status_code; - char filename[65535]; + char filename[65536]; uint16_t data_size; - char data[65535]; + char data[65536]; } 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[65535]; - char password[65535]; + char username[65536]; + char password[65536]; } 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[65535]; + char filename[65536]; } DNP3ObjectG70V3; typedef struct DNP3ObjectG70V4_ { @@ -1233,14 +1233,14 @@ typedef struct DNP3ObjectG70V4_ { uint16_t maximum_block_size; uint16_t request_id; uint8_t status_code; - char optional_text[255]; + char optional_text[256]; uint8_t optional_text_len; } DNP3ObjectG70V4; typedef struct DNP3ObjectG70V5_ { uint32_t file_handle; uint32_t block_number; - char file_data[255]; + char file_data[256]; uint8_t file_data_len; } DNP3ObjectG70V5; @@ -1248,7 +1248,7 @@ typedef struct DNP3ObjectG70V6_ { uint32_t file_handle; uint32_t block_number; uint8_t status_code; - char optional_text[255]; + char optional_text[256]; uint8_t optional_text_len; } DNP3ObjectG70V6; @@ -1260,11 +1260,11 @@ typedef struct DNP3ObjectG70V7_ { uint64_t created_timestamp; uint16_t permissions; uint16_t request_id; - char filename[65535]; + char filename[65536]; } DNP3ObjectG70V7; typedef struct DNP3ObjectG70V8_ { - char file_specification[65535]; + char file_specification[65536]; 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[65535]; + char error_text[65536]; 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[65535]; + char username[65536]; 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[65535]; + char username[65536]; uint8_t *master_challenge_data; } DNP3ObjectG120V11;