dnp3: explicit application layer length is bounded in uint16_t

Ticket: 8460
This commit is contained in:
Philippe Antoine
2026-05-16 20:42:15 +02:00
committed by Victor Julien
parent 658684a252
commit c25ccd299e
5 changed files with 339 additions and 493 deletions
+3 -3
View File
@@ -337,7 +337,7 @@ def gen_object_decoders(context):
{% for object in objects %}
{% if object.packed %}
static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint32_t *len,
static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint16_t *len,
uint8_t prefix_code, uint32_t start, uint32_t count,
DNP3PointList *points)
{
@@ -393,7 +393,7 @@ error:
}
{% else %}
static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint32_t *len,
static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint16_t *len,
uint8_t prefix_code, uint32_t start, uint32_t count,
DNP3PointList *points)
{
@@ -614,7 +614,7 @@ void DNP3FreeObjectPoint(int group, int variation, void *point)
* to a DNP3 application layer event will be returned.
*/
int DNP3DecodeObject(int group, int variation, const uint8_t **buf,
uint32_t *len, uint8_t prefix_code, uint32_t start,
uint16_t *len, uint8_t prefix_code, uint32_t start,
uint32_t count, DNP3PointList *points)
{
int rc = 0;
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -1455,9 +1455,8 @@ typedef struct DNP3ObjectG122V2_ {
/* END GENERATED CODE */
int DNP3DecodeObject(int group, int variation, const uint8_t **buf,
uint32_t *len, uint8_t prefix_code, uint32_t start, uint32_t count,
DNP3PointList *);
int DNP3DecodeObject(int group, int variation, const uint8_t **buf, uint16_t *len,
uint8_t prefix_code, uint32_t start, uint32_t count, DNP3PointList *);
DNP3PointList *DNP3PointListAlloc(void);
void DNP3FreeObjectPointList(int group, int variation, DNP3PointList *);
+21 -21
View File
@@ -181,12 +181,12 @@ static uint16_t DNP3ComputeCRC(const uint8_t *buf, uint32_t len)
*
* \retval 1 if CRC is OK, otherwise 0.
*/
static int DNP3CheckCRC(const uint8_t *block, uint32_t len)
static int DNP3CheckCRC(const uint8_t *block, uint16_t len)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return 1;
#endif
uint32_t crc_offset;
uint16_t crc_offset;
uint16_t crc;
/* Need at least one byte plus the CRC. */
@@ -224,10 +224,10 @@ static int DNP3CheckLinkHeaderCRC(const DNP3LinkHeader *header)
*
* \retval 1 if CRCs are OK, otherwise 0.
*/
static int DNP3CheckUserDataCRCs(const uint8_t *data, uint32_t len)
static int DNP3CheckUserDataCRCs(const uint8_t *data, uint16_t len)
{
uint32_t offset = 0;
uint32_t block_size;
uint16_t offset = 0;
uint16_t block_size;
while (offset < len) {
if (len - offset >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
@@ -336,7 +336,7 @@ static uint16_t DNP3ProbingParser(
*
* \retval The length of the buffer after CRCs are removed.
*/
static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
static int DNP3CalculateTransportLengthWithoutCRCs(uint16_t input_len)
{
/* Too small. */
if (input_len < DNP3_CRC_LEN) {
@@ -379,8 +379,8 @@ static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
*
* \retval 1 if reassembly was successful, otherwise 0.
*/
static int DNP3ReassembleApplicationLayer(const uint8_t *input,
uint32_t input_len, uint8_t **output, uint32_t *output_len)
static int DNP3ReassembleApplicationLayer(
const uint8_t *input, uint16_t input_len, uint8_t **output, uint16_t *output_len)
{
int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
@@ -408,8 +408,8 @@ static int DNP3ReassembleApplicationLayer(const uint8_t *input,
*output = ptr;
}
int offset = 0, block_size;
while ((uint32_t)offset < input_len) {
uint16_t offset = 0, block_size;
while (offset < input_len) {
if (input_len - offset > DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
}
@@ -536,9 +536,9 @@ static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request)
* \retval The length of the frame with CRCs included or 0 if the length isn't
* long enough to be a valid DNP3 frame.
*/
static uint32_t DNP3CalculateLinkLength(uint8_t length)
static uint16_t DNP3CalculateLinkLength(uint8_t length)
{
uint32_t frame_len = 0;
uint16_t frame_len = 0;
int rem;
/* Fail early if the length is less than the minimum size. */
@@ -703,8 +703,8 @@ static DNP3Object *DNP3ObjectAlloc(void)
* \retval 1 if all objects decoded, 0 if all objects could not be decoded (
* unknown group/variations)
*/
static int DNP3DecodeApplicationObjects(DNP3Transaction *tx, const uint8_t *buf,
uint32_t len, DNP3ObjectList *objects)
static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx, const uint8_t *buf, uint16_t len, DNP3ObjectList *objects)
{
int retval = 0;
uint64_t point_count = 0;
@@ -715,7 +715,7 @@ static int DNP3DecodeApplicationObjects(DNP3Transaction *tx, const uint8_t *buf,
}
while (len) {
uint32_t offset = 0;
uint16_t offset = 0;
if (len < sizeof(DNP3ObjHeader)) {
goto done;
@@ -880,7 +880,7 @@ done:
* \param input_len length of the input frame
*/
static void DNP3HandleUserDataRequest(
Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
Flow *f, DNP3State *dnp3, const uint8_t *input, uint16_t input_len)
{
DNP3LinkHeader *lh;
DNP3TransportHeader th;
@@ -967,14 +967,14 @@ static void DNP3HandleUserDataRequest(
}
static void DNP3HandleUserDataResponse(
Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
Flow *f, DNP3State *dnp3, const uint8_t *input, uint16_t input_len)
{
DNP3LinkHeader *lh;
DNP3TransportHeader th;
DNP3ApplicationHeader *ah;
DNP3InternalInd *iin;
DNP3Transaction *tx = NULL, *ttx;
uint32_t offset = 0;
uint16_t offset = 0;
lh = (DNP3LinkHeader *)input;
offset += sizeof(DNP3LinkHeader);
@@ -1073,7 +1073,7 @@ static int DNP3HandleRequestLinkLayer(
goto error;
}
uint32_t frame_len = DNP3CalculateLinkLength(header->len);
uint16_t frame_len = DNP3CalculateLinkLength(header->len);
if (frame_len == 0) {
DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
goto error;
@@ -1209,7 +1209,7 @@ static int DNP3HandleResponseLinkLayer(
}
/* Calculate the number of bytes needed to for this frame. */
uint32_t frame_len = DNP3CalculateLinkLength(header->len);
uint16_t frame_len = DNP3CalculateLinkLength(header->len);
if (frame_len == 0) {
DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
goto error;
@@ -1899,7 +1899,7 @@ static int DNP3ParserCheckLinkHeaderCRC(void)
*/
static int DNP3ReassembleApplicationLayerTest01(void)
{
uint32_t reassembled_len = 0;
uint16_t reassembled_len = 0;
uint8_t *output = NULL;
uint8_t payload[] = {
+1 -1
View File
@@ -221,7 +221,7 @@ typedef struct DNP3Transaction_ {
struct DNP3State_ *dnp3;
uint8_t *buffer; /**< Reassembled request buffer. */
uint32_t buffer_len;
uint16_t buffer_len;
DNP3ObjectList objects;
DNP3LinkHeader lh;
DNP3TransportHeader th;