From 8999afaa884bd8846c48c148c6b0bdb84320a745 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 17 Jul 2025 12:59:28 +0100 Subject: [PATCH] - added some additional checks in IedServer_updateVisibleStringAttributeValue and similar values (LIB61850-504) - added checks to avoid buffer underflow in IedServer_getFunctionalConstrainedData (LIB61850-505) --- src/iec61850/server/impl/ied_server.c | 107 ++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index 9125b638..1303a101 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -1317,6 +1317,9 @@ IedServer_updateAttributeValue(IedServer self, DataAttribute* dataAttribute, Mms assert(dataAttribute != NULL); assert(MmsValue_getType(dataAttribute->mmsValue) == MmsValue_getType(value)); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + if (MmsValue_equals(dataAttribute->mmsValue, value) == false) { if (dataAttribute->type == IEC61850_BOOLEAN) @@ -1350,6 +1353,12 @@ IedServer_updateFloatAttributeValue(IedServer self, DataAttribute* dataAttribute assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_FLOAT); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_FLOAT) + return; + float currentValue = MmsValue_toFloat(dataAttribute->mmsValue); if (currentValue != value) @@ -1374,6 +1383,12 @@ IedServer_updateInt32AttributeValue(IedServer self, DataAttribute* dataAttribute assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_INTEGER); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_INTEGER) + return; + int32_t currentValue = MmsValue_toInt32(dataAttribute->mmsValue); if (currentValue != value) @@ -1395,6 +1410,12 @@ IedServer_updateInt32AttributeValue(IedServer self, DataAttribute* dataAttribute void IedServer_updateDbposValue(IedServer self, DataAttribute* dataAttribute, Dbpos value) { + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_BIT_STRING) + return; + Dbpos currentValue = Dbpos_fromMmsValue(dataAttribute->mmsValue); if (currentValue != value) @@ -1420,6 +1441,12 @@ IedServer_updateInt64AttributeValue(IedServer self, DataAttribute* dataAttribute assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_INTEGER); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_INTEGER) + return; + int64_t currentValue = MmsValue_toInt64(dataAttribute->mmsValue); if (currentValue != value) @@ -1445,6 +1472,12 @@ IedServer_updateUnsignedAttributeValue(IedServer self, DataAttribute* dataAttrib assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_UNSIGNED); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_UNSIGNED) + return; + uint32_t currentValue = MmsValue_toUint32(dataAttribute->mmsValue); if (currentValue != value) @@ -1470,6 +1503,12 @@ IedServer_updateBitStringAttributeValue(IedServer self, DataAttribute* dataAttri assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_BIT_STRING); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_BIT_STRING) + return; + uint32_t currentValue = MmsValue_getBitStringAsInteger(dataAttribute->mmsValue); if (currentValue != value) @@ -1495,6 +1534,12 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu assert(dataAttribute != NULL); assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_BOOLEAN); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_BOOLEAN) + return; + bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue); if (currentValue != value) @@ -1529,6 +1574,12 @@ IedServer_updateVisibleStringAttributeValue(IedServer self, DataAttribute* dataA assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_VISIBLE_STRING); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_VISIBLE_STRING) + return; + const char* currentValue = MmsValue_toString(dataAttribute->mmsValue); if (strcmp(currentValue, value)) @@ -1554,6 +1605,12 @@ IedServer_updateUTCTimeAttributeValue(IedServer self, DataAttribute* dataAttribu assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_UTC_TIME); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_UTC_TIME) + return; + uint64_t currentValue = MmsValue_getUtcTimeInMs(dataAttribute->mmsValue); if (currentValue != value) @@ -1579,6 +1636,12 @@ IedServer_updateTimestampAttributeValue(IedServer self, DataAttribute* dataAttri assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_UTC_TIME); assert(self != NULL); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_UTC_TIME) + return; + if (memcmp(dataAttribute->mmsValue->value.utcTime, timestamp->val, 8)) { #if (CONFIG_MMS_THREADLESS_STACK != 1) @@ -1603,6 +1666,12 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu assert(MmsValue_getBitStringSize(dataAttribute->mmsValue) >= 12); assert(MmsValue_getBitStringSize(dataAttribute->mmsValue) <= 15); + if ((dataAttribute == NULL) || (dataAttribute->mmsValue == NULL)) + return; + + if (MmsValue_getType(dataAttribute->mmsValue) != MMS_BIT_STRING) + return; + uint32_t oldQuality = MmsValue_getBitStringAsInteger(dataAttribute->mmsValue); if (oldQuality != (uint32_t) quality) @@ -1814,8 +1883,26 @@ IedServer_getFunctionalConstrainedData(IedServer self, DataObject* dataObject, F { nameLen = strlen(dataObject->name); currentStart -= nameLen; + + if (currentStart < buffer) + { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: object path name too long (> 64 bytes)!\n"); + + goto exit_function; + } + memcpy(currentStart, dataObject->name, nameLen); currentStart--; + + if (currentStart < buffer) + { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: object path name too long (> 64 bytes)!\n"); + + goto exit_function; + } + *currentStart = '$'; if (dataObject->parent->modelType == DataObjectModelType) @@ -1826,6 +1913,17 @@ IedServer_getFunctionalConstrainedData(IedServer self, DataObject* dataObject, F char* fcString = FunctionalConstraint_toString(fc); + if (fcString == NULL) + goto exit_function; + + if (currentStart - 3 < buffer) + { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: object path name too long (> 64 bytes)!\n"); + + goto exit_function; + } + currentStart--; *currentStart = fcString[1]; currentStart--; @@ -1838,6 +1936,15 @@ IedServer_getFunctionalConstrainedData(IedServer self, DataObject* dataObject, F nameLen = strlen(ln->name); currentStart -= nameLen; + + if (currentStart < buffer) + { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: object path name too long (> 64 bytes)!\n"); + + goto exit_function; + } + memcpy(currentStart, ln->name, nameLen); LogicalDevice* ld = (LogicalDevice*) ln->parent;