From 3870bb382689434541f81e3671a405bc01ee2de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Fri, 20 Oct 2023 15:27:44 +0200 Subject: [PATCH 1/2] Fix decoding empty array of complex type in RPM --- src/bacnet/basic/service/h_rpm_a.c | 77 +++++++++++++++++------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/src/bacnet/basic/service/h_rpm_a.c b/src/bacnet/basic/service/h_rpm_a.c index b287dd3e..3869c90d 100644 --- a/src/bacnet/basic/service/h_rpm_a.c +++ b/src/bacnet/basic/service/h_rpm_a.c @@ -118,40 +118,49 @@ int rpm_ack_decode_service_request( more than one element to decode */ value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); rpm_property->value = value; - while (value && (apdu_len > 0)) { - len = bacapp_decode_known_property(apdu, (unsigned)apdu_len, - value, rpm_object->object_type, - rpm_property->propertyIdentifier); - /* If len == 0 then it's an empty structure, which is OK. */ - if (len < 0) { - /* problem decoding */ - PERROR("RPM Ack: unable to decode! %s:%s\n", - bactext_object_type_name(rpm_object->object_type), - bactext_property_name( - rpm_property->propertyIdentifier)); - /* note: caller will free the memory */ - return BACNET_STATUS_ERROR; - } - decoded_len += len; - apdu_len -= len; - apdu += len; - if (apdu_len && decode_is_closing_tag_number(apdu, 4)) { - decoded_len++; - apdu_len--; - apdu++; - break; - } else if (len > 0) { - old_value = value; - value = - calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); - old_value->next = value; - } else { - PERROR("RPM Ack: decoded %s:%s len=%d\n", - bactext_object_type_name(rpm_object->object_type), - bactext_property_name( - rpm_property->propertyIdentifier), - len); - break; + + /* Special case for an empty array - we decode it as null */ + if (apdu_len && decode_is_closing_tag_number(apdu, 4)) { + /* NULL value has tag 0, that was already set by calloc */ + decoded_len++; + apdu_len--; + apdu++; + } else { + while (value && (apdu_len > 0)) { + len = bacapp_decode_known_property(apdu, (unsigned)apdu_len, + value, rpm_object->object_type, + rpm_property->propertyIdentifier); + /* If len == 0 then it's an empty structure, which is OK. */ + if (len < 0) { + /* problem decoding */ + PERROR("RPM Ack: unable to decode! %s:%s\n", + bactext_object_type_name(rpm_object->object_type), + bactext_property_name( + rpm_property->propertyIdentifier)); + /* note: caller will free the memory */ + return BACNET_STATUS_ERROR; + } + decoded_len += len; + apdu_len -= len; + apdu += len; + if (apdu_len && decode_is_closing_tag_number(apdu, 4)) { + decoded_len++; + apdu_len--; + apdu++; + break; + } else if (len > 0) { + old_value = value; + value = + calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); + old_value->next = value; + } else { + PERROR("RPM Ack: decoded %s:%s len=%d\n", + bactext_object_type_name(rpm_object->object_type), + bactext_property_name( + rpm_property->propertyIdentifier), + len); + break; + } } } } else if (apdu_len && decode_is_opening_tag_number(apdu, 5)) { From 657973d3222215fb99b299646c5a7c31dff809b7 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Sat, 21 Oct 2023 08:45:18 -0500 Subject: [PATCH 2/2] format code --- src/bacnet/basic/service/h_rpm_a.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bacnet/basic/service/h_rpm_a.c b/src/bacnet/basic/service/h_rpm_a.c index 3869c90d..92d7564e 100644 --- a/src/bacnet/basic/service/h_rpm_a.c +++ b/src/bacnet/basic/service/h_rpm_a.c @@ -127,14 +127,16 @@ int rpm_ack_decode_service_request( apdu++; } else { while (value && (apdu_len > 0)) { - len = bacapp_decode_known_property(apdu, (unsigned)apdu_len, - value, rpm_object->object_type, + len = bacapp_decode_known_property(apdu, + (unsigned)apdu_len, value, rpm_object->object_type, rpm_property->propertyIdentifier); - /* If len == 0 then it's an empty structure, which is OK. */ + /* If len == 0 then it's an empty structure, which is + * OK. */ if (len < 0) { /* problem decoding */ PERROR("RPM Ack: unable to decode! %s:%s\n", - bactext_object_type_name(rpm_object->object_type), + bactext_object_type_name( + rpm_object->object_type), bactext_property_name( rpm_property->propertyIdentifier)); /* note: caller will free the memory */ @@ -150,12 +152,13 @@ int rpm_ack_decode_service_request( break; } else if (len > 0) { old_value = value; - value = - calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); + value = calloc( + 1, sizeof(BACNET_APPLICATION_DATA_VALUE)); old_value->next = value; } else { PERROR("RPM Ack: decoded %s:%s len=%d\n", - bactext_object_type_name(rpm_object->object_type), + bactext_object_type_name( + rpm_object->object_type), bactext_property_name( rpm_property->propertyIdentifier), len);