From: Erich Keane Date: Mon, 12 Jan 2015 17:51:31 +0000 (-0800) Subject: Fixed crash on rec'd invalid data. X-Git-Tag: 1.2.0+RC1~1967 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=65ecd8a508bf04d03153a9510a78995715242963;p=platform%2Fupstream%2Fiotivity.git Fixed crash on rec'd invalid data. 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 Signed-off-by: Erich Keane Reviewed-on: https://gerrit.iotivity.org/gerrit/103 Reviewed-by: Sashi Penta Tested-by: jenkins-iotivity --- diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h index a430f8b..8720a48 100644 --- a/resource/csdk/stack/include/ocstack.h +++ b/resource/csdk/stack/include/ocstack.h @@ -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, diff --git a/resource/include/OCException.h b/resource/include/OCException.h index b297a0c..8b74bd8 100644 --- a/resource/include/OCException.h +++ b/resource/include/OCException.h @@ -47,6 +47,11 @@ class OCException : public std::runtime_error return e.reason(); } + OCStackResult code() const + { + return m_reason; + } + private: OCStackResult m_reason; }; diff --git a/resource/include/OCResourceRequest.h b/resource/include/OCResourceRequest.h index 4ec5645..50c28c4 100644 --- a/resource/include/OCResourceRequest.h +++ b/resource/include/OCResourceRequest.h @@ -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& reps = info.representations(); - if(reps.size() >0) - { - std::vector::const_iterator itr = reps.begin(); - std::vector::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) { diff --git a/resource/makefile b/resource/makefile index a710781..87c1abd 100644 --- a/resource/makefile +++ b/resource/makefile @@ -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 diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp index 73aeb10..79f88a4 100644 --- a/resource/src/InProcClientWrapper.cpp +++ b/resource/src/InProcClientWrapper.cpp @@ -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: "<resJSONPayload<< ":" << std::flush; + throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON); + } + catch (cereal::Exception& ex) + { + oclog() <<"Cereal Exception in parseGetSetCallback: "<resJSONPayload<< ":" << std::flush; + throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON); + } std::vector::const_iterator it = oc.representations().begin(); if(it == oc.representations().end()) @@ -213,9 +228,17 @@ namespace OC ClientCallbackContext::DeviceListenContext* context = static_cast(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: " + <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 index 0000000..16abce1 --- /dev/null +++ b/resource/src/OCResourceRequest.cpp @@ -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 + +#include +#include +#include +#include + +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: "<& reps = info.representations(); + if(reps.size() >0) + { + std::vector::const_iterator itr = reps.begin(); + std::vector::const_iterator back = reps.end(); + m_representation = *itr; + ++itr; + + for(;itr != back; ++itr) + { + m_representation.addChild(*itr); + } + } + else + { + oclog() << "setPayload Error: "<