Skip to content

NULL pointer dereference in bacnet_device_object_reference_decode() when WriteProperty updates Structured View subordinate-list

High
skarg published GHSA-fv2r-c2m2-7qhh Jul 5, 2026

Package

bacnet-stack

Affected versions

1.4.0-1.4.3, 1.5.0

Patched versions

1.4.4, 1.5.1

Description

Summary

A NULL pointer dereference can be triggered in bacnet_device_object_reference_decode() when a WriteProperty request updates OBJECT_STRUCTURED_VIEW / PROP_SUBORDINATE_LIST in bacnet-stack v1.5.0.

The crash occurs because Structured_View_Subordinate_List_Member_Decode() calls:

bacnet_device_object_reference_decode(apdu, apdu_size, NULL);

and bacnet_device_object_reference_decode() later writes to value->deviceIdentifier in the len == 0 branch even when value == NULL.

This results in a segmentation fault / denial of service.

Affected version

  • v1.5.0

Impact

A crafted WriteProperty request can cause the server application to crash, resulting in denial of service.

Compile Command

cmake -S . -B build \
  -G "Unix Makefiles" \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_C_COMPILER=clang \
  -DCMAKE_C_FLAGS_DEBUG="-O0 -g3 -fno-omit-frame-pointer -fno-inline -fno-optimize-sibling-calls -fsanitize=address"

cmake --build build --target server -j"$(nproc)"

Actual behavior if applicable

AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5bdd5565f916 bp 0x7ffd78370010 sp 0x7ffd7836ff00 T0)

The outcome of ASAN

AddressSanitizer:DEADLYSIGNAL
=================================================================
==35603==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5bdd5565f916 bp 0x7ffd78370010 sp 0x7ffd7836ff00 T0)
==35603==The signal is caused by a WRITE memory access.
==35603==Hint: address points to the zero page.
    #0 0x5bdd5565f916 in bacnet_device_object_reference_decode /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492:38
    #1 0x5bdd5558cc60 in Structured_View_Subordinate_List_Member_Decode /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679:15
    #2 0x5bdd556558cc in bacnet_array_write /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918:19
    #3 0x5bdd5558bac3 in Structured_View_Write_Property /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668:35
    #4 0x5bdd5552b0ad in Device_Write_Property /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500:34
    #5 0x5bdd555b6eeb in handler_write_property /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140:27
    #6 0x5bdd555a6514 in apdu_handler /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609:17
    #7 0x5bdd555185b5 in npdu_handler /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279:21
    #8 0x5bdd5550fe3a in main /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423:13
    #9 0x70290fa2a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #10 0x70290fa2a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #11 0x5bdd55436514 in _start (/root/wc/bacnet/v1.5.0-verify/build-gdbasan/server+0x78514) (BuildId: 313c0d6263b1e368cd38c4758ea44eff9be27400)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492:38 in bacnet_device_object_reference_decode
==35603==ABORTING

GDB outcome

Breakpoint 2, Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
674         int len = 0;
(gdb) bt
#0  Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
#1  0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#2  0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#3  0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#4  0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#5  0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#6  0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#7  0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) frame 0
#0  Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
674         int len = 0;
(gdb) info args
object_instance = 1
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
(gdb) list 676,681
676
677         pObject = Keylist_Data(Object_List, object_instance);
678         if (pObject) {
679             len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680         }
681
(gdb) advance 679
Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
679             len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
(gdb) list 676,681
676
677         pObject = Keylist_Data(Object_List, object_instance);
678         if (pObject) {
679             len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680         }
681
(gdb) print apdu_size
$1 = 298
(gdb) step

Breakpoint 1, bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:471
471         int apdu_len = 0;
(gdb) info args
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
value = 0x0
(gdb) bt
#0  bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:471
#1  0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
#2  0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#3  0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#4  0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#5  0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#6  0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#7  0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#8  0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) list 480,495
480             &apdu[apdu_len], apdu_size - apdu_len, 0, &object_type,
481             &object_instance);
482         if (len > 0) {
483             apdu_len += len;
484             if (value) {
485                 value->deviceIdentifier.instance = object_instance;
486                 value->deviceIdentifier.type = object_type;
487             }
488         } else if (len < 0) {
489             return BACNET_STATUS_ERROR;
490         } else {
491             /* OPTIONAL - skip apdu_len increment */
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
493             value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
494         }
495         /* object-identifier [1] BACnetObjectIdentifier */
(gdb) tbreak /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
Temporary breakpoint 3 at 0x5555557f58d2: file /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c, line 492.
(gdb) c
Continuing.

Temporary breakpoint 3, bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) frame 0
#0  bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) info locals
len = 0
apdu_len = 0
object_type = OBJECT_ANALOG_INPUT
object_instance = 0
(gdb) print value
$2 = (BACNET_DEVICE_OBJECT_REFERENCE *) 0x0
(gdb) list 488,494
488         } else if (len < 0) {
489             return BACNET_STATUS_ERROR;
490         } else {
491             /* OPTIONAL - skip apdu_len increment */
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
493             value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
494         }
(gdb) list 472,481
472         BACNET_OBJECT_TYPE object_type = 0;
473         uint32_t object_instance = 0;
474
475         if (!apdu) {
476             return BACNET_STATUS_ERROR;
477         }
478         /* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
479         len = bacnet_object_id_context_decode(
480             &apdu[apdu_len], apdu_size - apdu_len, 0, &object_type,
481             &object_instance);
(gdb) x/24xb apdu
0x7ffff6003830: 0x8f    0x07    0x01    0x2d    0x41    0x56    0x2d    0x31
0x7ffff6003838: 0x2d    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffff6003840: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
(gdb) print/x apdu[0]
$3 = 0x8f
(gdb) print/x apdu[1]
$4 = 0x7
(gdb) print/x apdu[2]
$5 = 0x1
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) bt
#0  0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
#1  0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
#2  0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#3  0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#4  0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#5  0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#6  0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#7  0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#8  0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) frame 3
#3  0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
1668                wp_data->error_code = bacnet_array_write(
(gdb) info args
wp_data = 0x7ffff6003820
(gdb) print *wp_data
$6 = {
  object_instance = 1,
  object_type = OBJECT_STRUCTURED_VIEW,
  object_property = PROP_SUBORDINATE_LIST,
  array_index = 4294967295,
  application_data = "\217\a\001-AV-1-", 'A' <repeats 86 times>, "\000\000\000\002", 'A' <repeats 11 times>, "2", 'A' <repeats 18 times>, "\377", 'A' <repeats 19 times>, "0", 'A' <repeats 38 times>, "\020\000\000\000", 'A' <repeats 46 times>, "\276AAAAAAA\004\000\005:\016\f\001\300\000\001\036\tM\tU\t\b\t\b\t\b\t\t\t\t\t\b\t\t\t\t\t(AAAAAAAAA\200\000AAAAAAA;", '\000' <repeats 1177 times>,
  application_data_len = 298,
  priority = 16 '\020',
  error_class = ERROR_CLASS_OBJECT,
  error_code = ERROR_CODE_UNKNOWN_OBJECT
}
(gdb) list 1660,1670
1660                    status = Structured_View_Represents_Set(
1661                        wp_data->object_instance,
1662                        &value.type.Device_Object_Reference);
1663                }
1664                break;
1665            case PROP_SUBORDINATE_LIST:
1666                array_size = Structured_View_Subordinate_List_Count(
1667                    wp_data->object_instance);
1668                wp_data->error_code = bacnet_array_write(
1669                    wp_data->object_instance, wp_data->array_index,
1670                    Structured_View_Subordinate_List_Member_Decode,
(gdb) frame 2
#2  0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
5918                len = decode_function(
(gdb) info args
object_instance = 1
array_index = 4294967295
decode_function = 0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>
write_function = 0x555555722c70 <Structured_View_Subordinate_List_Member_Write>
array_size = 7
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
(gdb) list 5912,5922
5912                error_code = ERROR_CODE_ABORT_OTHER;
5913            }
5914        } else if (array_index == BACNET_ARRAY_ALL) {
5915            /* verify decoding of all elements */
5916            apdu_len = 0;
5917            for (index = 1; index <= array_size; index++) {
5918                len = decode_function(
5919                    object_instance, &apdu[apdu_len], apdu_size - apdu_len);
5920                if (len >= 0) {
5921                    apdu_len += len;
5922                } else {
(gdb) print array_index
$7 = 4294967295
(gdb) print apdu_size
$8 = 298
(gdb) frame 1
#1  0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
679             len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
(gdb) list 674,680
674         int len = 0;
675         struct object_data *pObject;
676
677         pObject = Keylist_Data(Object_List, object_instance);
678         if (pObject) {
679             len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680         }
(gdb) list 680,686
680         }
681
682         return len;
683     }
684
685     /**
686      * @brief Write a value to a BACnetARRAY property element value
(gdb) frame 0
#0  0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492             value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) list 495,510
495         /* object-identifier [1] BACnetObjectIdentifier */
496         len = bacnet_object_id_context_decode(
497             &apdu[apdu_len], apdu_size - apdu_len, 1, &object_type,
498             &object_instance);
499         if (len > 0) {
500             apdu_len += len;
501             if (value) {
502                 value->objectIdentifier.instance = object_instance;
503                 value->objectIdentifier.type = object_type;
504             }
505         } else {
506             return BACNET_STATUS_ERROR;
507         }
508
509         return apdu_len;
510     }

Reproduce

poc:

poc.zip

replay program:

replay.zip

usage:

BCNET_IFACE=lo BACNET_IP_PORT=47808 ./server
python3 replay.py 127.0.0.1 47808 poc/

Root cause

The issue is caused by inconsistent handling of a NULL output pointer in bacnet_device_object_reference_decode().

Call chain:

WriteProperty
  -> Device_Write_Property
  -> Structured_View_Write_Property
  -> bacnet_array_write
  -> Structured_View_Subordinate_List_Member_Decode
  -> bacnet_device_object_reference_decode

Relevant code path in structured_view.c:

len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);

Relevant code path in bacdevobjpropref.c:

/* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
len = bacnet_object_id_context_decode(
    &apdu[apdu_len], apdu_size - apdu_len, 0, &object_type,
    &object_instance);

if (len > 0) {
    apdu_len += len;
    if (value) {
        value->deviceIdentifier.instance = object_instance;
        value->deviceIdentifier.type = object_type;
    }
} else if (len < 0) {
    return BACNET_STATUS_ERROR;
} else {
    /* OPTIONAL - skip apdu_len increment */
    value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
    value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
}

The [0] device-identifier field is optional. When it is absent, bacnet_object_id_context_decode(..., tag=0, ...) returns len == 0, which is treated as an allowed condition. However, the else branch still unconditionally writes to value->deviceIdentifier.*, causing a NULL pointer dereference when value == NULL.

Trigger condition

The crash is reachable when processing a WriteProperty request for:

  • object_type = OBJECT_STRUCTURED_VIEW
  • object_property = PROP_SUBORDINATE_LIST
  • array_index = BACNET_ARRAY_ALL

During validation of array members, bacnet_array_write() calls the member decode function with the intent of checking decodability/length only, not storing the decoded structure. In that path, NULL is passed as the output pointer.

If the subordinate-list member encoding omits the optional [0] device-identifier but still reaches bacnet_device_object_reference_decode(), the len == 0 branch dereferences NULL.

GDB confirmation

During debugging, the following conditions were confirmed:

  1. Structured_View_Subordinate_List_Member_Decode() calls:
bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
  1. Inside bacnet_device_object_reference_decode():
  • value == 0x0

  • len == 0

  • execution reaches:

value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;

The crash occurs exactly at that write.

Suggested fix

Guard the len == 0 branch with if (value) as well:

} else {
    /* OPTIONAL - skip apdu_len increment */
    if (value) {
        value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
        value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
    }
}

An alternative defensive fix is to avoid passing NULL from Structured_View_Subordinate_List_Member_Decode() and instead decode into a temporary local structure.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE ID

CVE-2026-45341

Weaknesses

NULL Pointer Dereference

The product dereferences a pointer that it expects to be valid but is NULL. Learn more on MITRE.

Credits