Skip to content

Commit 3c5cfed

Browse files
authored
Merge branch 'bacnet-stack:master' into server-uci
2 parents e164798 + f66965d commit 3c5cfed

19 files changed

Lines changed: 901 additions & 167 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,4 @@ apps/piface/libpifacedigital/
114114
*.vcxproj.user
115115
.venv/
116116
.github/prompts
117+
.agents/

CHANGELOG.md

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,41 @@ The git repositories are hosted at the following sites:
1313
* <https://bacnet.sourceforge.net/>
1414
* <https://github.com/bacnet-stack/bacnet-stack/>
1515

16-
## [Unreleased] - 2026-05-29
16+
## [Unreleased] - 2026-06-29
1717

1818
### Security
1919

20+
* Secured lighting_command_decode out-of-bounds read, and enforce the
21+
FADE_TO and RAMP_TO required levels. (#1412)
22+
* Secure SCFailedConnectionRequest and SCDirectConnection decoder by
23+
adjusting the apdu size calculation. (#1413)
24+
* Secured RAMFS by checking read-only property for file size setting
25+
and zero new memory during realloc to prevent data leaking. (#1411)
26+
* Secured EPICs app property list management by adding append function. (#1409)
27+
* Secured Life Safety Zone member handling for write property. (#1410)
28+
* Secured the basic RAMFS to prevent buffer overrun during consecutive
29+
record appends and prevent heap out-of-bounds read during record
30+
replacement. (#1408)
31+
* Secured rpm_ack_decode_service_request buffer overflow by validating data
32+
length and remaining bytes. Added unit tests for
33+
handler_read_property_multiple_ack decoder paths. (#1395)
34+
* Secured BACnet/SC short proprietary option headers using BVLC-SC option
35+
header validation and rejecting proprietary options with hdr_len < 3
36+
(minimum vendor-id + option-type). Made proprietary option decode
37+
initialize outputs and only read vendor-id/option-type when hdr_len >= 3.
38+
Added a regression test that injects a malformed proprietary option
39+
and asserts decode fails with ERROR_CODE_HEADER_ENCODING_ERROR. (#1396)
40+
* Secured apps/router-mstp and apps/router-ipv6 routing, introducing
41+
routed_npdu_apdu_encode() with an explicit oversized-PDU drop check.
42+
Fixed protocol-version access (avoid reading pdu[0] when pdu_len == 0).
43+
Refactored logging in router applications to use debug_log_fprintf
44+
for consistent debug output. Refactored the router apps to use the
45+
bactext_debug_severity_strtol() for the BACNET_ROUTER_DEBUG environment
46+
variable. (#1392)
47+
* Secured the network control handler in the router-ipv6 and router-mstp apps
48+
to ensure proper offset calculation and prevent buffer overrun. (#1387)
49+
* Secured xy_color_decode() by adjusting apdu_size calculation to prevent
50+
out-of-bounds read. (#1386)
2051
* Secured the basic device object which had a string use after free.
2152
Added character string buffer stndup and same/diff functions.
2253
Changed all the device object character string handling to use
@@ -66,6 +97,16 @@ The git repositories are hosted at the following sites:
6697

6798
### Added
6899

100+
* Added .github/prompts to .gitignore
101+
* Add debug severity handling with ASCII string conversion functions into
102+
bactext module. Changed all the example apps to use the
103+
bactext_debug_severity_strtol() function for the "--debug" command
104+
line argument. (#1393)
105+
* Added Lighting_Output_Overridden_Ramp function. (#1389)
106+
* Added a lighting command override ramp function. Refactored the lighting
107+
commands to prevent them from meddling with tracking values and lighting
108+
operations while the light is overridden. (#1388)
109+
* Added BACNET_DEFINES variable to CMake build. (#1384)
69110
* Added BACnet/SC (BSC) datalink support to the modbus-gateway application.
70111
Extended GW_CONFIG with sc sub-struct holding all BACNET_SC_* fields, and
71112
added compile-time fallback: non-BSC binary + "bsc" JSON → warns and falls
@@ -115,6 +156,32 @@ The git repositories are hosted at the following sites:
115156

116157
### Changed
117158

159+
* Changed the GTK discover app to refresh objects quickly. Fixed object
160+
tree view to update a single row in place, preserving the selection.
161+
Implemented property value editing with Enter key commit control for
162+
WriteProperty. Refactored main window layout and default window size
163+
and column spacing constants for better usability. Removed REFRESH
164+
button. (#1390)
165+
* Changed compiler warnings to be stricter and remove unnecessary suppressions.
166+
Apply const correctness across multiple files, including datalink interface
167+
name parameters across multiple files. Apply const qualifications to the
168+
character buffer string functions. Apply const correctness to string
169+
parameters in bacapp.c and bacapp.h. Revise parsing of const strings using
170+
bacnet_stptok() to tokenize. Add bacnet_strncpy to ensure null-terminated
171+
partial string copying. Replace strncpy with bacnet_strncpy for safer string
172+
copying in modbus_rtu and point_table modules. Fixed file compile warnings
173+
where the "no previous declaration" is being generated. Fixed floating-point
174+
arithmetic by adding type casts for clarity, including a changing
175+
color_rgb_clamp to use float instead of double to fix compiler float
176+
conversion warnings. Refactor hostname validation and encoding functions
177+
for const correctness and improved string handling.
178+
Renamed routed_get_my_address to Routed_Device_Get_My_Address and
179+
update references for consistency with BAC_ROUTING.
180+
Refactor Ringbuf functions to remove unnecessary volatile qualifiers
181+
and casting to improve type safety. Use cast to uintptr_t for specific
182+
casting to const where appropriate. Enable additional compiler warnings
183+
in unit tests and treat them as errors to enforce clean builds.
184+
Add parse_primitive_value function to handle primitive data parsing. (#1385)
118185
* Changed debug_print to debug_log_fprintf in ReadRange handler. (#1303)
119186
* Changed logging in many modules to use debug_log_fprintf for consistent
120187
error and debug output that can be adjusted during runtime. (#1364)
@@ -150,6 +217,17 @@ The git repositories are hosted at the following sites:
150217

151218
### Fixed
152219

220+
* Fixed out-of-bounds write in Read Property ACK closing tag encoding. (#1407)
221+
* Fixed AV COV change on out-of-service writes by marking them. (#1406)
222+
* Fixed GetEventInformation service choice in error reply. (#1405)
223+
* Fixed device object property value codec by advancing cursor. (#1404)
224+
* Fixed Recipient_List decode by advancing the cursor for list elements. (#1402)
225+
* Fixed GetAlarmSummary to accept empty request. (#1401)
226+
* Fixed Binary_Lighting_Output_Create to initialize Time_Of_Active_Time_Reset
227+
and Time_Of_Strike_Count_Reset using datetime_wildcard_set.
228+
* Fixed access credential object initialization to use datetime_wildcard_set
229+
for activation and expiration times.
230+
* Fixed C89 build warnings from modbus gateway application. (#1383)
153231
* Fixed ReadRange service request to reject for missing mandatory parameters
154232
in Read Range request. (#1303)
155233
* Fixed BACnet/SC primary hub reconnection logic when connected to failover
@@ -204,6 +282,8 @@ The git repositories are hosted at the following sites:
204282

205283
### Removed
206284

285+
* Remove unnecessary LEGACY=true flag from build commands in Makefile,
286+
workflows, and scripts. (#1383)
207287
* Removed unmaintained ports/uip, ports/arduino_uno, ports/pic18*,
208288
and ports/rx62n folders and references. (#1324)
209289

apps/epics/main.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ static uint32_t Property_List_Length = 0;
112112
static uint32_t Property_List_Index = 0;
113113
static int32_t Property_List[MAX_PROPS + 2];
114114

115+
static bool property_list_append(int32_t property_id)
116+
{
117+
uint32_t capacity =
118+
(uint32_t)(sizeof(Property_List) / sizeof(Property_List[0]));
119+
120+
/* Keep one slot free for the list terminator and cap to MAX_PROPS. */
121+
if ((Property_List_Index >= (capacity - 1)) ||
122+
(Property_List_Index >= MAX_PROPS)) {
123+
return false;
124+
}
125+
126+
Property_List[Property_List_Index] = property_id;
127+
Property_List_Index++;
128+
Property_List_Length++;
129+
130+
return true;
131+
}
132+
115133
struct property_value_list_t {
116134
int32_t property_id;
117135
BACNET_APPLICATION_DATA_VALUE *value;
@@ -842,10 +860,11 @@ ProcessRPMData(BACNET_READ_ACCESS_DATA *rpm_data, EPICS_STATES state)
842860
bHasStructuredViewList = true;
843861
break;
844862
default:
845-
Property_List[Property_List_Index] =
846-
rpm_property->propertyIdentifier;
847-
Property_List_Index++;
848-
Property_List_Length++;
863+
if (!property_list_append(
864+
(int32_t)rpm_property->propertyIdentifier)) {
865+
/* Ignore excess properties once local list is full.
866+
*/
867+
}
849868
break;
850869
}
851870
/* Free up the value(s) */
@@ -905,18 +924,24 @@ ProcessRPMData(BACNET_READ_ACCESS_DATA *rpm_data, EPICS_STATES state)
905924
} else if (bSuccess) { /* and GET_LIST_OF_ALL_RESPONSE */
906925
/* Now append the properties we waited on. */
907926
if (bHasStructuredViewList) {
908-
Property_List[Property_List_Index] = PROP_STRUCTURED_OBJECT_LIST;
909-
Property_List_Index++;
910-
Property_List_Length++;
927+
if (!property_list_append(PROP_STRUCTURED_OBJECT_LIST)) {
928+
/* Ignore when local list is full. */
929+
}
911930
}
912931
if (bHasObjectList) {
913-
Property_List[Property_List_Index] = PROP_OBJECT_LIST;
914-
Property_List_Index++;
915-
Property_List_Length++;
932+
if (!property_list_append(PROP_OBJECT_LIST)) {
933+
/* Ignore when local list is full. */
934+
}
916935
}
917936
/* Now insert the -1 list terminator, but don't count it. */
918-
Property_List[Property_List_Index] = -1;
919-
assert(Property_List_Length < MAX_PROPS);
937+
if (Property_List_Index <
938+
(uint32_t)(sizeof(Property_List) / sizeof(Property_List[0]))) {
939+
Property_List[Property_List_Index] = -1;
940+
} else {
941+
Property_List
942+
[(sizeof(Property_List) / sizeof(Property_List[0])) - 1] = -1;
943+
}
944+
assert(Property_List_Length <= MAX_PROPS);
920945
Property_List_Index = 0; /* Will start at top of the list */
921946
nextState = GET_PROPERTY_REQUEST;
922947
}

src/bacnet/bacapp.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6162,6 +6162,9 @@ int bacapp_device_object_property_value_encode(
61626162
if (value->property_array_index != BACNET_ARRAY_ALL) {
61636163
len = encode_context_unsigned(apdu, 3, value->property_array_index);
61646164
apdu_len += len;
6165+
if (apdu) {
6166+
apdu += len;
6167+
}
61656168
}
61666169
len = encode_opening_tag(apdu, 4);
61676170
apdu_len += len;
@@ -6263,7 +6266,8 @@ int bacapp_device_object_property_value_decode(
62636266
value->property_array_index = BACNET_ARRAY_ALL;
62646267
}
62656268
}
6266-
if (bacnet_is_opening_tag_number(apdu, apdu_size, 4, &len)) {
6269+
if (bacnet_is_opening_tag_number(
6270+
&apdu[apdu_len], apdu_size - apdu_len, 4, &len)) {
62676271
/* property-value [4] ABSTRACT-SYNTAX.&Type */
62686272
apdu_len += len;
62696273
if (value) {
@@ -6276,11 +6280,14 @@ int bacapp_device_object_property_value_decode(
62766280
} else {
62776281
return BACNET_STATUS_ERROR;
62786282
}
6279-
if (bacnet_is_closing_tag_number(apdu, apdu_size, 4, &len)) {
6283+
if (bacnet_is_closing_tag_number(
6284+
&apdu[apdu_len], apdu_size - apdu_len, 4, &len)) {
62806285
apdu_len += len;
62816286
} else {
62826287
return BACNET_STATUS_ERROR;
62836288
}
6289+
} else {
6290+
return BACNET_STATUS_ERROR;
62846291
}
62856292

62866293
return apdu_len;

src/bacnet/basic/object/av.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
993993
status = write_property_type_valid(
994994
wp_data, &value, BACNET_APPLICATION_TAG_BOOLEAN);
995995
if (status) {
996-
CurrentAV->Out_Of_Service = value.type.Boolean;
996+
Analog_Value_Out_Of_Service_Set(
997+
wp_data->object_instance, value.type.Boolean);
997998
}
998999
break;
9991000
case PROP_UNITS:

src/bacnet/basic/object/bacfile.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,11 @@ bool bacfile_file_size_set(
649649

650650
pObject = Keylist_Data(Object_List, object_instance);
651651
if (pObject) {
652-
if (pObject->File_Access_Stream) {
653-
status =
654-
bacfile_file_size_set_callback(pObject->Pathname, file_size);
652+
if (!pObject->Read_Only) {
653+
if (pObject->File_Access_Stream) {
654+
status = bacfile_file_size_set_callback(
655+
pObject->Pathname, file_size);
656+
}
655657
}
656658
}
657659

0 commit comments

Comments
 (0)