Fixed crash on rec'd invalid data.
authorErich Keane <erich.keane@intel.com>
Mon, 12 Jan 2015 17:51:31 +0000 (09:51 -0800)
committerSudarshan Prasad <sudarshan.prasad@intel.com>
Thu, 22 Jan 2015 02:45:56 +0000 (02:45 +0000)
This issue is a fix for IOT 114.

Previously, a bad series of JSON coming in would cause an exception
to be thrown. this would result in the callback/server crashing, which
is not appropriate behavior. This fix catches and logs any JSON
errors keeping the callback/server from crashing.

NOTE: This changeset is originally from 01.org(changeset 695,
author: Erich Keane).

Change-Id: I1e7d042f243bc1b86771778c308f1187bcda875f
Signed-Off-by:Sudarshan Prasad<sudarshan.prasad@intel.com>
Signed-off-by: Erich Keane <erich.keane@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/103
Reviewed-by: Sashi Penta <sashi.kumar.penta@intel.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
resource/csdk/stack/include/ocstack.h
resource/include/OCException.h
resource/include/OCResourceRequest.h
resource/makefile
resource/src/InProcClientWrapper.cpp
resource/src/OCResourceRequest.cpp [new file with mode: 0644]
resource/src/SConscript

index a430f8b..8720a48 100644 (file)
@@ -167,6 +167,7 @@ typedef enum {
     OC_STACK_PERSISTENT_BUFFER_REQUIRED,
     OC_STACK_INVALID_REQUEST_HANDLE,
     OC_STACK_INVALID_DEVICE_INFO,
+    OC_STACK_INVALID_JSON,
     /* NOTE: Insert all new error codes here!*/
     #ifdef WITH_PRESENCE
     OC_STACK_PRESENCE_STOPPED = 128,
index b297a0c..8b74bd8 100644 (file)
@@ -47,6 +47,11 @@ class OCException : public std::runtime_error
             return e.reason();
         }
 
+        OCStackResult code() const
+        {
+            return m_reason;
+        }
+
     private:
         OCStackResult m_reason;
 };
index 4ec5645..50c28c4 100644 (file)
@@ -170,34 +170,7 @@ namespace OC
             m_requestType = requestType;
         }
 
-        void setPayload(const std::string& requestPayload)
-        {
-            if(requestPayload.empty())
-            {
-                return;
-            }
-
-            MessageContainer info;
-            info.setJSONRepresentation(requestPayload);
-
-            const std::vector<OCRepresentation>& reps = info.representations();
-            if(reps.size() >0)
-            {
-                std::vector<OCRepresentation>::const_iterator itr = reps.begin();
-                std::vector<OCRepresentation>::const_iterator back = reps.end();
-                m_representation = *itr;
-                ++itr;
-
-                for(;itr != back; ++itr)
-                {
-                    m_representation.addChild(*itr);
-                }
-            }
-            else
-            {
-                throw OCException(OC::Exception::INVALID_REPRESENTATION);
-            }
-        }
+        void setPayload(const std::string& requestPayload);
 
         void setQueryParams(QueryParamsMap& queryParams)
         {
index a710781..87c1abd 100644 (file)
@@ -87,8 +87,8 @@ cpp_sdk: prep_dirs c_sdk liboc.a
 examples: liboc.a
        cd examples && $(MAKE) apps "BUILD=$(BUILD)"
 
-liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o
-       ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o
+liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o OCResourceRequest.o
+       ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o $(OBJ_DIR)/OCResourceRequest.o
 
 OCPlatform_impl.o: src/OCPlatform_impl.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform_impl.cpp $(CXX_INC)
@@ -114,6 +114,9 @@ InProcServerWrapper.o: src/InProcServerWrapper.cpp
 InProcClientWrapper.o: src/InProcClientWrapper.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/InProcClientWrapper.cpp $(CXX_INC)
 
+OCResourceRequest.o: src/OCResourceRequest.cpp
+       $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResourceRequest.cpp $(CXX_INC)
+
 clean: clean_legacy
        -rm -rf release
        -rm -rf debug
index 73aeb10..79f88a4 100644 (file)
@@ -100,7 +100,22 @@ namespace OC
         }
 
         MessageContainer oc;
-        oc.setJSONRepresentation(clientResponse->resJSONPayload);
+        try
+        {
+            oc.setJSONRepresentation(clientResponse->resJSONPayload);
+        }
+        catch (cereal::RapidJSONException& ex)
+        {
+            oclog() <<"RapidJSON Exception in parseGetSetCallback: "<<ex.what() <<std::endl<<
+                "Data was:"<< clientResponse->resJSONPayload<< ":" << std::flush;
+            throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON);
+        }
+        catch (cereal::Exception& ex)
+        {
+            oclog() <<"Cereal Exception in parseGetSetCallback: "<<ex.what() <<std::endl<<
+                "Data was:"<< clientResponse->resJSONPayload<< ":" << std::flush;
+            throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON);
+        }
 
         std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
         if(it == oc.representations().end())
@@ -213,9 +228,17 @@ namespace OC
         ClientCallbackContext::DeviceListenContext* context =
             static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
 
-        OCRepresentation rep = parseGetSetCallback(clientResponse);
-        std::thread exec(context->callback, rep);
-        exec.detach();
+        try
+        {
+            OCRepresentation rep = parseGetSetCallback(clientResponse);
+            std::thread exec(context->callback, rep);
+            exec.detach();
+        }
+        catch(OC::OCException& e)
+        {
+            oclog() <<"Exception in listenDeviceCallback, ignoring response: "
+                <<e.what() <<std::flush;
+        }
 
         return OC_STACK_KEEP_TRANSACTION;
     }
@@ -289,13 +312,21 @@ namespace OC
 
         OCRepresentation rep;
         HeaderOptions serverHeaderOptions;
-        if(clientResponse->result == OC_STACK_OK)
+        OCStackResult result = clientResponse->result;
+        if(result == OC_STACK_OK)
         {
             parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            rep = parseGetSetCallback(clientResponse);
+            try
+            {
+                rep = parseGetSetCallback(clientResponse);
+            }
+            catch(OC::OCException& e)
+            {
+                result = e.code();
+            }
         }
 
-        std::thread exec(context->callback, serverHeaderOptions, rep, clientResponse->result);
+        std::thread exec(context->callback, serverHeaderOptions, rep, result);
         exec.detach();
         return OC_STACK_DELETE_TRANSACTION;
     }
@@ -349,15 +380,23 @@ namespace OC
         OCRepresentation attrs;
         HeaderOptions serverHeaderOptions;
 
-        if (OC_STACK_OK               == clientResponse->result ||
-            OC_STACK_RESOURCE_CREATED == clientResponse->result ||
-            OC_STACK_RESOURCE_DELETED == clientResponse->result)
+        OCStackResult result = clientResponse->result;
+        if (OC_STACK_OK               == result ||
+            OC_STACK_RESOURCE_CREATED == result ||
+            OC_STACK_RESOURCE_DELETED == result)
         {
             parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            attrs = parseGetSetCallback(clientResponse);
+            try
+            {
+                attrs = parseGetSetCallback(clientResponse);
+            }
+            catch(OC::OCException& e)
+            {
+                result = e.code();
+            }
         }
 
-        std::thread exec(context->callback, serverHeaderOptions, attrs, clientResponse->result);
+        std::thread exec(context->callback, serverHeaderOptions, attrs, result);
         exec.detach();
         return OC_STACK_DELETE_TRANSACTION;
     }
@@ -551,13 +590,21 @@ namespace OC
         OCRepresentation attrs;
         HeaderOptions serverHeaderOptions;
         uint32_t sequenceNumber = clientResponse->sequenceNumber;
+        OCStackResult result = clientResponse->result;
         if(clientResponse->result == OC_STACK_OK)
         {
             parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            attrs = parseGetSetCallback(clientResponse);
+            try
+            {
+                attrs = parseGetSetCallback(clientResponse);
+            }
+            catch(OC::OCException& e)
+            {
+                result = e.code();
+            }
         }
         std::thread exec(context->callback, serverHeaderOptions, attrs,
-                    clientResponse->result, sequenceNumber);
+                    result, sequenceNumber);
         exec.detach();
         if(sequenceNumber == OC_OBSERVE_DEREGISTER)
         {
diff --git a/resource/src/OCResourceRequest.cpp b/resource/src/OCResourceRequest.cpp
new file mode 100644 (file)
index 0000000..16abce1
--- /dev/null
@@ -0,0 +1,74 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <OCResourceRequest.h>
+
+#include <vector>
+#include <map>
+#include <cereal/cereal.hpp>
+#include <OicJsonSerializer.hpp>
+
+using namespace OC;
+using namespace std;
+
+void OCResourceRequest::setPayload(const std::string& requestPayload)
+{
+    MessageContainer info;
+
+    if(requestPayload.empty())
+    {
+        return;
+    }
+
+    try
+    {
+        info.setJSONRepresentation(requestPayload);
+    }
+    catch(cereal::RapidJSONException& ex)
+    {
+        oclog() << "RapidJSON Exception in setPayload: "<<ex.what()<<std::endl<<
+            "Data was:"<<requestPayload<<std::flush;
+        return;
+    }
+    catch(cereal::Exception& ex)
+    {
+        oclog() << "Cereal Exception in setPayload: "<<ex.what()<<std::endl<<
+            "Data was:"<<requestPayload<<std::flush;
+        return;
+    }
+
+    const std::vector<OCRepresentation>& reps = info.representations();
+    if(reps.size() >0)
+    {
+        std::vector<OCRepresentation>::const_iterator itr = reps.begin();
+        std::vector<OCRepresentation>::const_iterator back = reps.end();
+        m_representation = *itr;
+        ++itr;
+
+        for(;itr != back; ++itr)
+        {
+            m_representation.addChild(*itr);
+        }
+    }
+    else
+    {
+        oclog() << "setPayload Error: "<<OC::Exception::INVALID_REPRESENTATION<< std::flush;
+    }
+}
index 3a50c87..682ca47 100644 (file)
@@ -45,7 +45,8 @@ oclib_src = [
                'OCException.cpp',
                'OCRepresentation.cpp',
                'InProcServerWrapper.cpp',
-               'InProcClientWrapper.cpp'
+               'InProcClientWrapper.cpp',
+               'OCResourceRequest.cpp'
        ]
 
 shared_oclib = oclib_env.SharedLibrary('oc', oclib_src)