Merge pull request #533 from openweave/bug/network-telemetry-mgr-fixes-contd

Network telemetry mgr fixes contd
diff --git a/src/lib/profiles/data-management/Current/ResourceIdentifier.cpp b/src/lib/profiles/data-management/Current/ResourceIdentifier.cpp
index a86c618..a6ca135 100644
--- a/src/lib/profiles/data-management/Current/ResourceIdentifier.cpp
+++ b/src/lib/profiles/data-management/Current/ResourceIdentifier.cpp
@@ -57,8 +57,8 @@
     }
     else if (ResourceType == Schema::Weave::Common::RESOURCE_TYPE_DEVICE)
     {
-            err = aWriter.Put(aTag, ResourceId);
-            SuccessOrExit(err);
+        err = aWriter.Put(aTag, ResourceId);
+        SuccessOrExit(err);
     }
     else
     {
@@ -222,38 +222,61 @@
     const char * resourceName;
     char * endPtr;
     uint32_t r_lower, r_upper;
-    char uintbuffer[9];
+    const size_t hexDigitsInInt32 = 8;
+    char uintbuffer[hexDigitsInInt32 + 1];
 
     for (resourceType = Schema::Weave::Common::RESOURCE_TYPE_DEVICE; resourceType <= Schema::Weave::Common::RESOURCE_TYPE_SERVICE;
          resourceType++)
     {
-        resourceName = ResourceTypeAsString(resourceType);
+        resourceName                 = ResourceTypeAsString(resourceType);
+        const size_t resourceNameLen = (resourceName == NULL ? 0 : strlen(resourceName));
 
         if (resourceName == NULL)
             continue;
 
-        if ((strlen(resourceName) + 1) > bufferLen)
+        if ((resourceNameLen + 1) > bufferLen)
             continue;
 
-        if ((strncmp(resourceName, inBuffer, strlen(resourceName)) == 0) && inBuffer[strlen(resourceName)] == '_')
+        if ((strncmp(resourceName, inBuffer, resourceNameLen) == 0) && inBuffer[resourceNameLen] == '_')
         {
+            // Ensure there is at least 1 character after the prefix.
+            bufferLen -= resourceNameLen + 1;
+            VerifyOrExit(bufferLen > 1, err = WEAVE_ERROR_INVALID_ARGUMENT);
             // skip over the prefix
-            inBuffer += strlen(resourceName) + 1;
+            inBuffer += resourceNameLen + 1;
             break;
         }
     }
 
     VerifyOrExit(resourceType <= Schema::Weave::Common::RESOURCE_TYPE_SERVICE, err = WEAVE_ERROR_INVALID_ARGUMENT);
 
-    memcpy(uintbuffer, inBuffer, 8);
-    uintbuffer[8] = '\0';
-    r_upper     = strtoul(uintbuffer, &endPtr, 16);
-    VerifyOrExit(strlen(endPtr) == 0, err = WEAVE_ERROR_INVALID_ARGUMENT);
+    // Content after the 16 hexadecimal digits will be ignored.
+    if (bufferLen > (2 * hexDigitsInInt32))
+        bufferLen = (2 * hexDigitsInInt32);
 
-    memcpy(uintbuffer, inBuffer + 8, 8);
-    uintbuffer[8] = '\0';
-    r_lower     = strtoul(inBuffer + 8, &endPtr, 16);
-    VerifyOrExit(strlen(endPtr) == 0, err = WEAVE_ERROR_INVALID_ARGUMENT);
+    if (bufferLen > hexDigitsInInt32)
+    {
+        memcpy(uintbuffer, inBuffer + bufferLen - hexDigitsInInt32, hexDigitsInInt32);
+        uintbuffer[hexDigitsInInt32] = '\0';
+
+        r_lower = strtoul(uintbuffer, &endPtr, 16);
+        VerifyOrExit(strlen(endPtr) == 0, err = WEAVE_ERROR_INVALID_ARGUMENT);
+
+        memset(uintbuffer, 0, sizeof(uintbuffer));
+        memcpy(uintbuffer, inBuffer, bufferLen - hexDigitsInInt32);
+
+        r_upper = strtoul(uintbuffer, &endPtr, 16);
+        VerifyOrExit(strlen(endPtr) == 0, err = WEAVE_ERROR_INVALID_ARGUMENT);
+    }
+    else
+    {
+        r_upper = 0;
+        memset(uintbuffer, 0, sizeof(uintbuffer));
+        memcpy(uintbuffer, inBuffer, bufferLen);
+
+        r_lower = strtoul(uintbuffer, &endPtr, 16);
+        VerifyOrExit(strlen(endPtr) == 0, err = WEAVE_ERROR_INVALID_ARGUMENT);
+    }
 
     ResourceId   = ((uint64_t) r_upper) << 32 | ((uint64_t) r_lower);
     ResourceType = resourceType;
diff --git a/src/test-apps/TestResourceIdentifier.cpp b/src/test-apps/TestResourceIdentifier.cpp
index 22f729e..d562b35 100644
--- a/src/test-apps/TestResourceIdentifier.cpp
+++ b/src/test-apps/TestResourceIdentifier.cpp
@@ -406,16 +406,24 @@
     ResourceIdentifier resource(Schema::Weave::Common::RESOURCE_TYPE_DEVICE, 0x18b4300000000001ULL);
     ResourceIdentifier resource1(0x18b4300000000001ULL);
     ResourceIdentifier resource2(Schema::Weave::Common::RESOURCE_TYPE_USER, 0x18b4300000000001ULL);
+    ResourceIdentifier resource3(Schema::Weave::Common::RESOURCE_TYPE_DEVICE, 1ULL);
+    ResourceIdentifier resource4(Schema::Weave::Common::RESOURCE_TYPE_DEVICE, 0x0000000100000001ULL);
     ResourceIdentifier resource_self(ResourceIdentifier::SELF_NODE_ID);
     ResourceIdentifier resource_unknown_type(0xC001, 0x18b4300000000001ULL);
     ResourceIdentifier resource_uninitialized;
 
-    const char * resource_str               = "DEVICE_18B4300000000001";
-    const char * resource2_str              = "USER_18B4300000000001";
-    const char * resource_self_str          = "RESERVED_DEVICE_SELF";
-    const char * resource_uninitialized_str = "RESERVED_NOT_SPECIFIED";
-    const char * resource_unknown_type_str  = "(C001)_18B4300000000001";
-    const char * resource_unknown_str       = "WIDGET_18B4300000000001";
+    const char resource_str[]               = "DEVICE_18B4300000000001";
+    const char resource2_str[]              = "USER_18B4300000000001";
+    const char resource_self_str[]          = "RESERVED_DEVICE_SELF";
+    const char resource_uninitialized_str[] = "RESERVED_NOT_SPECIFIED";
+    const char resource_unknown_type_str[]  = "(C001)_18B4300000000001";
+    const char resource_unknown_str[]       = "WIDGET_18B4300000000001";
+    const char resource_str_long_1[]        = "DEVICE_18B43000000000011";
+    const char resource_str_long_2[]        = "DEVICE_18B4300000000001meaningless_padding";
+    const char resource_str_short_1[]       = "DEVICE_01";
+    const char resource_str_short_2[]       = "DEVICE_0000001";
+    const char resource_str_short_3[]       = "DEVICE_10000001";
+    const char resource_str_err_1[]         = "DEVICE_-1";
 
     char resource_buf[ResourceIdentifier::MAX_STRING_LENGTH];
     WEAVE_ERROR err;
@@ -446,6 +454,31 @@
     NL_TEST_ASSERT(inSuite, resource_uninitialized == resource);
     NL_TEST_ASSERT(inSuite, resource_uninitialized != resource_self);
 
+    err = resource_uninitialized.FromString(resource_str_long_1, sizeof(resource_str_long_1));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, resource_uninitialized == resource);
+    NL_TEST_ASSERT(inSuite, resource_uninitialized != resource_self);
+
+    err = resource_uninitialized.FromString(resource_str_long_2, sizeof(resource_str_long_2));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, resource_uninitialized == resource);
+    NL_TEST_ASSERT(inSuite, resource_uninitialized != resource_self);
+
+    err = resource_uninitialized.FromString(resource_str_short_1, sizeof(resource_str_short_1));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+    resource_uninitialized.ToString(resource_buf, sizeof(resource_buf));
+    NL_TEST_ASSERT(inSuite, resource_uninitialized == resource3);
+
+    err = resource_uninitialized.FromString(resource_str_short_2, sizeof(resource_str_short_2));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+    resource_uninitialized.ToString(resource_buf, sizeof(resource_buf));
+    NL_TEST_ASSERT(inSuite, resource_uninitialized == resource3);
+
+    err = resource_uninitialized.FromString(resource_str_short_3, sizeof(resource_str_short_3));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+    resource_uninitialized.ToString(resource_buf, sizeof(resource_buf));
+    NL_TEST_ASSERT(inSuite, resource_uninitialized == resource4);
+
     // verify we map onto self node id
     err = resource_uninitialized.FromString(resource_str, sizeof(resource_str), 0x18b4300000000001ULL);
     NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
@@ -469,6 +502,9 @@
 
     err = resource_uninitialized.FromString(resource_unknown_str, sizeof(resource_unknown_str));
     NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_INVALID_ARGUMENT);
+
+    err = resource_uninitialized.FromString(resource_unknown_str, sizeof(resource_str_err_1));
+    NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_INVALID_ARGUMENT);
 }
 
 static int TestSetup(void * inContext)