- MMS client: improved handling of malformed messages when receiving reports

- MMS client: fixed potential memory leak when receiving malformed messages
pull/147/head
Michael Zillgith 7 years ago
parent 0d49e8c1d2
commit 233cd20fd0

@ -43,6 +43,8 @@ struct sClientReport
char* dataSetName; char* dataSetName;
int dataSetNameSize; /* size of the dataSetName buffer */ int dataSetNameSize; /* size of the dataSetName buffer */
int dataSetSize;
MmsValue* entryId; MmsValue* entryId;
MmsValue* dataReferences; MmsValue* dataReferences;
MmsValue* dataSetValues; MmsValue* dataSetValues;
@ -93,6 +95,8 @@ ClientReport_create()
{ {
ClientReport self = (ClientReport) GLOBAL_CALLOC(1, sizeof(struct sClientReport)); ClientReport self = (ClientReport) GLOBAL_CALLOC(1, sizeof(struct sClientReport));
self->dataSetSize = -1;
return self; return self;
} }
@ -607,6 +611,18 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
int dataSetSize = MmsValue_getBitStringSize(inclusion); int dataSetSize = MmsValue_getBitStringSize(inclusion);
if (matchingReport->dataSetSize == -1) {
matchingReport->dataSetSize = dataSetSize;
}
else {
if (dataSetSize != matchingReport->dataSetSize) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (inclusion has no plausible size)\n");
goto exit_function;
}
}
int includedElements = MmsValue_getNumberOfSetBits(inclusion); int includedElements = MmsValue_getNumberOfSetBits(inclusion);
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
@ -692,7 +708,7 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
MmsValue_update(dataSetElement, newElementValue); MmsValue_update(dataSetElement, newElementValue);
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: update element value type: %i\n", MmsValue_getType(newElementValue)); printf("IED_CLIENT: update element value type: %i\n", MmsValue_getType(newElementValue));
valueIndex++; valueIndex++;

@ -437,39 +437,41 @@ informationReportHandler(void* parameter, char* domainName,
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: received information report for %s\n", variableListName); printf("DEBUG_IED_CLIENT: received information report for %s\n", variableListName);
if (domainName == NULL) { if (value) {
if (domainName == NULL) {
if (isVariableListName) { if (isVariableListName) {
private_IedConnection_handleReport(self, value); private_IedConnection_handleReport(self, value);
} }
else {
if (strcmp(variableListName, "LastApplError") == 0)
handleLastApplErrorMessage(self, value);
else { else {
if (DEBUG_IED_CLIENT) if (strcmp(variableListName, "LastApplError") == 0)
printf("IED_CLIENT: Received unknown variable list report for list: %s\n", variableListName); handleLastApplErrorMessage(self, value);
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: Received unknown variable list report for list: %s\n", variableListName);
}
} }
} }
} else {
else { if (DEBUG_IED_CLIENT)
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: RCVD CommandTermination for %s/%s\n", domainName, variableListName);
printf("IED_CLIENT: RCVD CommandTermination for %s/%s\n", domainName, variableListName);
LinkedList control = LinkedList_getNext(self->clientControls); LinkedList control = LinkedList_getNext(self->clientControls);
while (control != NULL) { while (control != NULL) {
ControlObjectClient object = (ControlObjectClient) control->data; ControlObjectClient object = (ControlObjectClient) control->data;
char* objectRef = ControlObjectClient_getObjectReference(object); char* objectRef = ControlObjectClient_getObjectReference(object);
if (doesReportMatchControlObject(domainName, variableListName, objectRef)) if (doesReportMatchControlObject(domainName, variableListName, objectRef))
private_ControlObjectClient_invokeCommandTerminationHandler(object); private_ControlObjectClient_invokeCommandTerminationHandler(object);
control = LinkedList_getNext(control); control = LinkedList_getNext(control);
}
} }
}
MmsValue_delete(value); MmsValue_delete(value);
}
} }
static IedConnection static IedConnection

@ -138,23 +138,23 @@ mmsClient_parseGetVariableAccessAttributesResponse(ByteBuffer* message, uint32_t
asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message)); (void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));
if (rval.code != RC_OK) if (rval.code == RC_OK) {
return NULL;
if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) { if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
if (invokeId != NULL) if (invokeId != NULL)
*invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu); *invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu);
if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
ConfirmedServiceResponse_PR_getVariableAccessAttributes) ConfirmedServiceResponse_PR_getVariableAccessAttributes)
{ {
GetVariableAccessAttributesResponse_t* response; GetVariableAccessAttributesResponse_t* response;
response = &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.getVariableAccessAttributes); response = &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.getVariableAccessAttributes);
TypeSpecification_t* asnTypeSpec = &response->typeSpecification; TypeSpecification_t* asnTypeSpec = &response->typeSpecification;
typeSpec = createTypeSpecification(asnTypeSpec); typeSpec = createTypeSpecification(asnTypeSpec);
}
} }
} }

@ -1190,6 +1190,9 @@ MmsValue_deleteIfNotNull(MmsValue* self)
void void
MmsValue_delete(MmsValue* self) MmsValue_delete(MmsValue* self)
{ {
if (self == NULL)
return;
switch (self->type) switch (self->type)
{ {
case MMS_INTEGER: case MMS_INTEGER:

Loading…
Cancel
Save