From 0d49e8c1d22ac278251c8ecf875754bc3b80ea6d Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 22 Jan 2019 11:37:48 +0100 Subject: [PATCH] - MMS client: improved handling of incorrect messages when reading data --- src/iec61850/client/ied_connection.c | 15 +- src/iec61850/server/mms_mapping/control.c | 6 +- .../iso_mms/client/mms_client_connection.c | 6 +- src/mms/iso_mms/client/mms_client_read.c | 262 ++++++++++++------ src/mms/iso_mms/common/mms_common_msg.c | 221 +++++++++++---- src/mms/iso_mms/common/mms_value.c | 14 +- 6 files changed, 387 insertions(+), 137 deletions(-) diff --git a/src/iec61850/client/ied_connection.c b/src/iec61850/client/ied_connection.c index de323ef4..04593f9f 100644 --- a/src/iec61850/client/ied_connection.c +++ b/src/iec61850/client/ied_connection.c @@ -95,6 +95,9 @@ iedConnection_mapMmsErrorToIedError(MmsError mmsError) case MMS_ERROR_ACCESS_OBJECT_VALUE_INVALID: return IED_ERROR_OBJECT_VALUE_INVALID; + case MMS_ERROR_PARSING_RESPONSE: + return IED_ERROR_OBJECT_VALUE_INVALID; + default: return IED_ERROR_UNKNOWN; } @@ -2291,7 +2294,7 @@ exit_function: } ClientDataSet -IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const char* dataSetReference, +IedConnection_readDataSetValues(IedConnection self, IedClientError* err, const char* dataSetReference, ClientDataSet dataSet) { char domainIdBuffer[65]; @@ -2316,14 +2319,14 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); if (domainId == NULL) { - *error = IED_ERROR_OBJECT_REFERENCE_INVALID; + *err = IED_ERROR_OBJECT_REFERENCE_INVALID; goto exit_function; } const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1; if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) { - *error = IED_ERROR_OBJECT_REFERENCE_INVALID; + *err = IED_ERROR_OBJECT_REFERENCE_INVALID; goto exit_function; } @@ -2346,15 +2349,15 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const dataSetVal = MmsConnection_readNamedVariableListValuesAssociationSpecific(self->connection, &mmsError, itemId, true); else - dataSetVal= MmsConnection_readNamedVariableListValues(self->connection, &mmsError, + dataSetVal = MmsConnection_readNamedVariableListValues(self->connection, &mmsError, domainId, itemId, true); if (dataSetVal == NULL) { - *error = iedConnection_mapMmsErrorToIedError(mmsError); + *err = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } else - *error = IED_ERROR_OK; + *err = IED_ERROR_OK; if (dataSet == NULL) { dataSet = ClientDataSet_create(dataSetReference); diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c index 2febf484..b411f777 100644 --- a/src/iec61850/server/mms_mapping/control.c +++ b/src/iec61850/server/mms_mapping/control.c @@ -316,10 +316,12 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char* self->iedServer = iedServer; MmsVariableSpecification* ctlValSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "ctlVal", NULL); - self->ctlVal = MmsValue_newDefaultValue(ctlValSpec); + if (ctlValSpec != NULL) + self->ctlVal = MmsValue_newDefaultValue(ctlValSpec); MmsVariableSpecification* originSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "origin", NULL); - self->origin = MmsValue_newDefaultValue(originSpec); + if (originSpec != NULL) + self->origin = MmsValue_newDefaultValue(originSpec); self->ctlNum = MmsValue_newUnsigned(8); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index b6a05546..b93ef4f3 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -1697,9 +1697,13 @@ MmsConnection_readNamedVariableListValues(MmsConnection self, MmsError* mmsError ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError); - if (responseMessage != NULL) + if (responseMessage != NULL) { value = mmsClient_parseReadResponse(self->lastResponse, NULL, true); + if (value == NULL) + *mmsError = MMS_ERROR_PARSING_RESPONSE; + } + releaseResponse(self); exit_function: diff --git a/src/mms/iso_mms/client/mms_client_read.c b/src/mms/iso_mms/client/mms_client_read.c index 30a211c6..2a29812e 100644 --- a/src/mms/iso_mms/client/mms_client_read.c +++ b/src/mms/iso_mms/client/mms_client_read.c @@ -46,6 +46,9 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi int i = 0; for (i = 0; i < elementCount; i++) { + + value = NULL; + AccessResult_PR presentType = accessResultList[i]->present; if (presentType == AccessResult_PR_failure) { @@ -66,72 +69,138 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_UNKNOWN); } else if (presentType == AccessResult_PR_array) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_ARRAY; int arrayElementCount = accessResultList[i]->choice.array.list.count; - value->value.structure.size = arrayElementCount; - value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*)); - - int j; - - for (j = 0; j < arrayElementCount; j++) { - value->value.structure.components[j] = mmsMsg_parseDataElement( - accessResultList[i]->choice.array.list.array[j]); + if (arrayElementCount > 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_ARRAY; + value->value.structure.size = arrayElementCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*)); + + int j; + + for (j = 0; j < arrayElementCount; j++) { + value->value.structure.components[j] = mmsMsg_parseDataElement( + accessResultList[i]->choice.array.list.array[j]); + + if (value->value.structure.components[j] == NULL) { + MmsValue_delete(value); + value = NULL; + break; + } + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid array size)!\n"); } + } else if (presentType == AccessResult_PR_structure) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_STRUCTURE; int componentCount = accessResultList[i]->choice.structure.list.count; - value->value.structure.size = componentCount; - value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); - - int j; - for (j = 0; j < componentCount; j++) { - value->value.structure.components[j] = mmsMsg_parseDataElement( - accessResultList[i]->choice.structure.list.array[j]); + if (componentCount > 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_STRUCTURE; + value->value.structure.size = componentCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); + + int j; + for (j = 0; j < componentCount; j++) { + value->value.structure.components[j] = mmsMsg_parseDataElement( + accessResultList[i]->choice.structure.list.array[j]); + + if (value->value.structure.components[j] == NULL) { + MmsValue_delete(value); + value = NULL; + break; + } + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid structure size)!\n"); } + } else if (presentType == AccessResult_PR_bitstring) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_BIT_STRING; + int size = accessResultList[i]->choice.bitstring.size; - value->value.bitString.size = (size * 8) - - accessResultList[i]->choice.bitstring.bits_unused; + if (size > 0) { + + int maxSize = (size * 8); + int bitSize = maxSize - accessResultList[i]->choice.bitstring.bits_unused; + + if ((bitSize > 0) && (maxSize >= bitSize)) { + + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_BIT_STRING; - value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); - memcpy(value->value.bitString.buf, - accessResultList[i]->choice.bitstring.buf, size); + + value->value.bitString.size = (size * 8) + - accessResultList[i]->choice.bitstring.bits_unused; + + value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); + memcpy(value->value.bitString.buf, + accessResultList[i]->choice.bitstring.buf, size); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (bit string padding problem)!\n"); + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (bit string size 0 or negative)!\n"); + } } else if (presentType == AccessResult_PR_integer) { - Asn1PrimitiveValue* berInteger = - BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf, - accessResultList[i]->choice.integer.size); - value = MmsValue_newIntegerFromBerInteger(berInteger); + int size = accessResultList[i]->choice.integer.size; + + if (size > 0) { + Asn1PrimitiveValue* berInteger = + BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf, size); + + value = MmsValue_newIntegerFromBerInteger(berInteger); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid integer size)!\n"); + } } else if (presentType == AccessResult_PR_unsigned) { - Asn1PrimitiveValue* berInteger = - BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf, - accessResultList[i]->choice.Unsigned.size); - value = MmsValue_newUnsignedFromBerInteger(berInteger); + int size = accessResultList[i]->choice.Unsigned.size; + + if (size > 0) { + Asn1PrimitiveValue* berInteger = + BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf, + accessResultList[i]->choice.Unsigned.size); + + value = MmsValue_newUnsignedFromBerInteger(berInteger); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid unsigned size)!\n"); + } + } else if (presentType == AccessResult_PR_floatingpoint) { - int size = accessResultList[i]->choice.floatingpoint.size; - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_FLOAT; + int size = accessResultList[i]->choice.floatingpoint.size; if (size == 5) { /* FLOAT32 */ + + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_FLOAT; + value->value.floatingPoint.formatWidth = 32; value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0]; @@ -146,8 +215,11 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi #endif } + else if (size == 9) { /* FLOAT64 */ + + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_FLOAT; - if (size == 9) { /* FLOAT64 */ value->value.floatingPoint.formatWidth = 64; value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0]; @@ -161,46 +233,70 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi memcpy(value->value.floatingPoint.buf, floatBuf, 8); #endif } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing float (size must be 5 or 9, is %i)\n", size); + } } else if (presentType == AccessResult_PR_visiblestring) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - - value->type = MMS_VISIBLE_STRING; int strSize = accessResultList[i]->choice.visiblestring.size; - value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); - value->value.visibleString.size = strSize; + if (strSize >= 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + + value->type = MMS_VISIBLE_STRING; + value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); + value->value.visibleString.size = strSize; - memcpy(value->value.visibleString.buf, - accessResultList[i]->choice.visiblestring.buf, - strSize); + memcpy(value->value.visibleString.buf, + accessResultList[i]->choice.visiblestring.buf, + strSize); + + value->value.visibleString.buf[strSize] = 0; + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid visible-string size)\n"); + } - value->value.visibleString.buf[strSize] = 0; } else if (presentType == AccessResult_PR_mMSString) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - - value->type = MMS_STRING; int strSize = accessResultList[i]->choice.mMSString.size; - value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); - value->value.visibleString.size = strSize; + if (strSize >= 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - memcpy(value->value.visibleString.buf, - accessResultList[i]->choice.mMSString.buf, strSize); + value->type = MMS_STRING; + value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); + value->value.visibleString.size = strSize; - value->value.visibleString.buf[strSize] = 0; + memcpy(value->value.visibleString.buf, + accessResultList[i]->choice.mMSString.buf, strSize); + value->value.visibleString.buf[strSize] = 0; + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid mms-string size)\n"); + } } else if (presentType == AccessResult_PR_utctime) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_UTC_TIME; - memcpy(value->value.utcTime, - accessResultList[i]->choice.utctime.buf, 8); + int size = accessResultList[i]->choice.utctime.size; + + if (size == 8) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + + value->type = MMS_UTC_TIME; + memcpy(value->value.utcTime, accessResultList[i]->choice.utctime.buf, 8); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing UTC time (size is %i instead of 8\n", size); + } } else if (presentType == AccessResult_PR_boolean) { value = MmsValue_newBoolean(accessResultList[i]->choice.boolean); @@ -208,25 +304,36 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi else if (presentType == AccessResult_PR_binarytime) { int size = accessResultList[i]->choice.binarytime.size; - if (size <= 6) { + if ((size == 4) || (size == 6)) { value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value->type = MMS_BINARY_TIME; value->value.binaryTime.size = size; memcpy(value->value.binaryTime.buf, accessResultList[i]->choice.binarytime.buf, size); } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing binary time (size must be 4 or 6, is %i\n", size); + } } else if (presentType == AccessResult_PR_octetstring) { int size = accessResultList[i]->choice.octetstring.size; - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_OCTET_STRING; - value->value.octetString.maxSize = size; - value->value.octetString.size = size; - value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size); - memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size); + if (size >= 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_OCTET_STRING; + value->value.octetString.maxSize = size; + value->value.octetString.size = size; + value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size); + memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing access result (invalid octet-string size)\n"); + } } else { - printf("unknown type %i\n", presentType); + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: unknown type %i in access result\n", presentType); value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID); } @@ -254,21 +361,20 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message)); - if (rval.code != RC_OK) - return NULL; - - if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) { + if (rval.code == RC_OK) { + if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) { - if (invokeId != NULL) - *invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu); + if (invokeId != NULL) + *invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu); - if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == ConfirmedServiceResponse_PR_read) { - ReadResponse_t* response = &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.read); + if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == ConfirmedServiceResponse_PR_read) { + ReadResponse_t* response = &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.read); - int elementCount = response->listOfAccessResult.list.count; + int elementCount = response->listOfAccessResult.list.count; - valueList = mmsClient_parseListOfAccessResults(response->listOfAccessResult.list.array, - elementCount, createArray); + valueList = mmsClient_parseListOfAccessResults(response->listOfAccessResult.list.array, + elementCount, createArray); + } } } diff --git a/src/mms/iso_mms/common/mms_common_msg.c b/src/mms/iso_mms/common/mms_common_msg.c index 47673a48..38cb34f9 100644 --- a/src/mms/iso_mms/common/mms_common_msg.c +++ b/src/mms/iso_mms/common/mms_common_msg.c @@ -185,80 +185,175 @@ mmsMsg_parseDataElement(Data_t* dataElement) { MmsValue* value = NULL; - if (dataElement->present == Data_PR_structure) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + if (dataElement->present == Data_PR_array) { + + int componentCount = dataElement->choice.array->list.count; + + if (componentCount > 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + + value->type = MMS_ARRAY; + value->value.structure.size = componentCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); + + int i; + + for (i = 0; i < componentCount; i++) { + value->value.structure.components[i] = + mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]); + + if (value->value.structure.components[i] == NULL) { + MmsValue_delete(value); + value = NULL; + break; + } + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (invalid array size)!\n"); + } + + } + else if (dataElement->present == Data_PR_structure) { int componentCount = dataElement->choice.structure->list.count; - value->type = MMS_STRUCTURE; - value->value.structure.size = componentCount; - value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); + if (componentCount > 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + + value->type = MMS_STRUCTURE; + value->value.structure.size = componentCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); + + int i; - int i; + for (i = 0; i < componentCount; i++) { + value->value.structure.components[i] = + mmsMsg_parseDataElement(dataElement->choice.structure->list.array[i]); - for (i = 0; i < componentCount; i++) { - value->value.structure.components[i] = - mmsMsg_parseDataElement(dataElement->choice.structure->list.array[i]); + if (value->value.structure.components[i] == NULL) { + MmsValue_delete(value); + value = NULL; + break; + } + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (invalid structure size)!\n"); } } else if (dataElement->present == Data_PR_array) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); int componentCount = dataElement->choice.array->list.count; - value->type = MMS_ARRAY; - value->value.structure.size = componentCount; - value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); + if (componentCount > 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - int i; + value->type = MMS_ARRAY; + value->value.structure.size = componentCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); - for (i = 0; i < componentCount; i++) { - value->value.structure.components[i] = - mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]); + int i; + + for (i = 0; i < componentCount; i++) { + value->value.structure.components[i] = + mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]); + + if (value->value.structure.components[i] == NULL) { + MmsValue_delete(value); + value = NULL; + break; + } + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (invalid array size)!\n"); } + } else { if (dataElement->present == Data_PR_integer) { - Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( - dataElement->choice.integer.buf, dataElement->choice.integer.size); - value = MmsValue_newIntegerFromBerInteger(berInteger); + if (dataElement->choice.integer.size > 0) { + Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( + dataElement->choice.integer.buf, dataElement->choice.integer.size); + + value = MmsValue_newIntegerFromBerInteger(berInteger); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (invalid integer size)!\n"); + } } else if (dataElement->present == Data_PR_unsigned) { - Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( - dataElement->choice.Unsigned.buf, dataElement->choice.Unsigned.size); - value = MmsValue_newUnsignedFromBerInteger(berInteger); + if (dataElement->choice.Unsigned.size > 0) { + Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( + dataElement->choice.Unsigned.buf, dataElement->choice.Unsigned.size); + + value = MmsValue_newUnsignedFromBerInteger(berInteger); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (invalid unsigned size)!\n"); + } } else if (dataElement->present == Data_PR_visiblestring) { - value = MmsValue_newVisibleStringFromByteArray(dataElement->choice.visiblestring.buf, - dataElement->choice.visiblestring.size); + + if (dataElement->choice.visiblestring.size >= 0) { + value = MmsValue_newVisibleStringFromByteArray(dataElement->choice.visiblestring.buf, + dataElement->choice.visiblestring.size); + } } else if (dataElement->present == Data_PR_mMSString) { - value = MmsValue_newMmsStringFromByteArray(dataElement->choice.mMSString.buf, - dataElement->choice.mMSString.size); + + if ( dataElement->choice.mMSString.size >= 0) { + value = MmsValue_newMmsStringFromByteArray(dataElement->choice.mMSString.buf, + dataElement->choice.mMSString.size); + } } else if (dataElement->present == Data_PR_bitstring) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_BIT_STRING; int size = dataElement->choice.bitstring.size; - value->value.bitString.size = (size * 8) - - dataElement->choice.bitstring.bits_unused; + if (size > 0) { + + int maxSize = (size * 8); + int bitSize = maxSize - dataElement->choice.bitstring.bits_unused; - value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); - memcpy(value->value.bitString.buf, - dataElement->choice.bitstring.buf, size); + if ((bitSize > 0) && (maxSize >= bitSize)) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_BIT_STRING; + + value->value.bitString.size = bitSize; + + value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); + memcpy(value->value.bitString.buf, + dataElement->choice.bitstring.buf, size); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (bit string padding problem)!\n"); + } + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing data element (bit string size 0 or negative)!\n"); + } } else if (dataElement->present == Data_PR_floatingpoint) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - int size = dataElement->choice.floatingpoint.size; - value->type = MMS_FLOAT; + int size = dataElement->choice.floatingpoint.size; if (size == 5) { /* FLOAT32 */ + + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_FLOAT; + value->value.floatingPoint.formatWidth = 32; value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0]; @@ -273,6 +368,10 @@ mmsMsg_parseDataElement(Data_t* dataElement) } if (size == 9) { /* FLOAT64 */ + + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_FLOAT; + value->value.floatingPoint.formatWidth = 64; value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0]; @@ -287,33 +386,58 @@ mmsMsg_parseDataElement(Data_t* dataElement) } } else if (dataElement->present == Data_PR_utctime) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_UTC_TIME; - memcpy(value->value.utcTime, dataElement->choice.utctime.buf, 8); + + int size = dataElement->choice.utctime.size; + + if (size == 8) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_UTC_TIME; + memcpy(value->value.utcTime, dataElement->choice.utctime.buf, 8); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing UTC time (size is %i instead of 8\n", size); + } } else if (dataElement->present == Data_PR_octetstring) { - value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_OCTET_STRING; - int size = dataElement->choice.octetstring.size; - value->value.octetString.size = size; - value->value.octetString.maxSize = size; - value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size); - memcpy(value->value.octetString.buf, dataElement->choice.octetstring.buf, size); + + if (dataElement->choice.octetstring.size >= 0) { + value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); + value->type = MMS_OCTET_STRING; + int size = dataElement->choice.octetstring.size; + value->value.octetString.size = size; + value->value.octetString.maxSize = size; + value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size); + memcpy(value->value.octetString.buf, dataElement->choice.octetstring.buf, size); + } + } else if (dataElement->present == Data_PR_binarytime) { int size = dataElement->choice.binarytime.size; - if (size <= 6) { + if ((size == 4) || (size == 6)) { value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value->type = MMS_BINARY_TIME; value->value.binaryTime.size = size; memcpy(value->value.binaryTime.buf, dataElement->choice.binarytime.buf, size); } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: error parsing binary time (size must be 4 or 6, is %i\n", size); + } } else if (dataElement->present == Data_PR_boolean) { value = MmsValue_newBoolean(dataElement->choice.boolean); } + else if (dataElement->present == Data_PR_booleanArray) { + + } + + } + if (DEBUG_MMS_CLIENT) { + if (value == NULL) + printf("MMS CLIENT: error parsing data element\n"); } return value; @@ -350,7 +474,6 @@ void mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName) { #if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) - // strncpy(extendedFileName, MmsServerConnection_getFilesystemBasepath(self), 512); strncpy(extendedFileName, basepath, 512); strncat(extendedFileName, fileName, 512); #else diff --git a/src/mms/iso_mms/common/mms_value.c b/src/mms/iso_mms/common/mms_value.c index 1d8485e2..b6ae3430 100644 --- a/src/mms/iso_mms/common/mms_value.c +++ b/src/mms/iso_mms/common/mms_value.c @@ -1081,10 +1081,12 @@ MmsValue_cloneToBuffer(const MmsValue* self, uint8_t* destinationAddress) return destinationAddress; } -// create a deep clone MmsValue* MmsValue_clone(const MmsValue* self) { + if (self == NULL) + return NULL; + MmsValue* newValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); if (newValue == NULL) @@ -2010,6 +2012,16 @@ MmsValue_getTypeString(MmsValue* self) const char* MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize) { + if (self == NULL) { + strncpy(buffer, "(null)", bufferSize); + + /* Ensure buffer is always 0 terminated */ + if (bufferSize > 0) + buffer[bufferSize - 1] = 0; + + return buffer; + } + switch (MmsValue_getType(self)) { case MMS_STRUCTURE: