Parcourir la source

Merge pull request #488 from Wtango/tmp

fix bug what case segment fualt when writing to a readonly value
Sten Grüner il y a 9 ans
Parent
commit
c3d4c52e0b
2 fichiers modifiés avec 57 ajouts et 4 suppressions
  1. 11 4
      src/server/ua_services_attribute.c
  2. 46 0
      tests/check_services_attributes.c

+ 11 - 4
src/server/ua_services_attribute.c

@@ -136,10 +136,14 @@ static UA_StatusCode getVariableNodeValue(const UA_VariableNode *vn, const UA_Ti
         if(retval == UA_STATUSCODE_GOOD)
             handleSourceTimestamps(timestamps, v);
     } else {
-        UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
-                                      timestamps == UA_TIMESTAMPSTORETURN_BOTH);
-        retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId,
-                                           sourceTimeStamp, rangeptr, v);
+        if(vn->value.dataSource.read == NULL) {
+            retval = UA_STATUSCODE_BADINTERNALERROR;
+        } else {
+            UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
+                                          timestamps == UA_TIMESTAMPSTORETURN_BOTH);
+            retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId,
+                                               sourceTimeStamp, rangeptr, v);
+        }
     }
 
     if(rangeptr)
@@ -469,6 +473,9 @@ Service_Write_single_ValueDataSource(UA_Server *server, UA_Session *session, con
     UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_VARIABLETYPE);
     UA_assert(node->valueSource == UA_VALUESOURCE_DATASOURCE);
 
+    if(node->value.dataSource.write == NULL)
+        return UA_STATUSCODE_BADWRITENOTSUPPORTED;
+
     UA_StatusCode retval;
     if(wvalue->indexRange.length <= 0) {
         retval = node->value.dataSource.write(node->value.dataSource.handle, node->nodeId,

+ 46 - 0
tests/check_services_attributes.c

@@ -35,6 +35,19 @@ static UA_Server* makeTestSequence(void) {
     UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
                               parentReferenceNodeId, myIntegerName,
                               UA_NODEID_NULL, vattr, NULL);
+	
+    /* DataSource VariableNode */
+    UA_VariableAttributes_init(&vattr);
+    UA_DataSource temperatureDataSource = (UA_DataSource) {
+                                           .handle = NULL, .read = NULL, .write = NULL};
+    vattr.description = UA_LOCALIZEDTEXT("en_US","temperature");
+    vattr.displayName = UA_LOCALIZEDTEXT("en_US","temperature");
+    UA_Server_addDataSourceVariableNode(server, UA_NODEID_STRING(1, "cpu.temperature"),
+                                        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
+					UA_QUALIFIEDNAME(1, "cpu temperature"),
+                                        UA_NODEID_NULL, vattr, temperatureDataSource, NULL);
+
     
     /* VariableNode with array */
     UA_VariableAttributes_init(&vattr);
@@ -579,6 +592,23 @@ START_TEST(ReadSingleAttributeUserExecutableWithoutTimestamp) {
 #endif
 } END_TEST
 
+START_TEST(ReadSingleDataSourceAttributeValueWithoutTimestamp) {
+    UA_Server *server = makeTestSequence();
+    UA_DataValue resp;
+    UA_DataValue_init(&resp);
+    UA_ReadRequest rReq;
+    UA_ReadRequest_init(&rReq);
+    rReq.nodesToRead = UA_ReadValueId_new();
+    rReq.nodesToReadSize = 1;
+    rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "cpu.temperature");
+    rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
+    Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER, &rReq.nodesToRead[0], &resp);
+    ck_assert_int_eq(UA_STATUSCODE_BADINTERNALERROR, resp.status);
+    UA_Server_delete(server);
+    UA_ReadRequest_deleteMembers(&rReq);
+    UA_DataValue_deleteMembers(&resp);
+} END_TEST
+
 /* Tests for writeValue method */
 
 START_TEST(WriteSingleAttributeNodeId) {
@@ -908,6 +938,20 @@ START_TEST(WriteSingleAttributeUserExecutable) {
     UA_Server_delete(server);
 } END_TEST
 
+START_TEST(WriteSingleDataSourceAttributeValue) {
+    UA_Server *server = makeTestSequence();
+    UA_WriteValue wValue;
+    UA_WriteValue_init(&wValue);
+    UA_Int32 testValue = 0;
+    UA_Variant_setScalar(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_INT32]);
+    wValue.nodeId = UA_NODEID_STRING(1, "cpu.temperature");
+    wValue.attributeId = UA_ATTRIBUTEID_VALUE;
+    wValue.value.hasValue = UA_TRUE;
+    UA_StatusCode retval = Service_Write_single(server, &adminSession, &wValue);
+    ck_assert_int_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
+    UA_Server_delete(server);
+} END_TEST
+
 START_TEST(numericRange) {
     UA_NumericRange range;
     const UA_String str = (UA_String){9, (UA_Byte*)"1:2,0:3,5"};
@@ -950,6 +994,7 @@ static Suite * testSuite_services_attributes(void) {
 	tcase_add_test(tc_readSingleAttributes, ReadSingleAttributeHistorizingWithoutTimestamp);
 	tcase_add_test(tc_readSingleAttributes, ReadSingleAttributeExecutableWithoutTimestamp);
 	tcase_add_test(tc_readSingleAttributes, ReadSingleAttributeUserExecutableWithoutTimestamp);
+	tcase_add_test(tc_readSingleAttributes, ReadSingleDataSourceAttributeValueWithoutTimestamp);
 
 	suite_add_tcase(s, tc_readSingleAttributes);
 
@@ -976,6 +1021,7 @@ static Suite * testSuite_services_attributes(void) {
 	tcase_add_test(tc_writeSingleAttributes, WriteSingleAttributeHistorizing);
 	tcase_add_test(tc_writeSingleAttributes, WriteSingleAttributeExecutable);
 	tcase_add_test(tc_writeSingleAttributes, WriteSingleAttributeUserExecutable);
+	tcase_add_test(tc_writeSingleAttributes, WriteSingleDataSourceAttributeValue);
 
 	suite_add_tcase(s, tc_writeSingleAttributes);