Skip to content

Commit

Permalink
Bug/crash in patch entity attrs when relationship without object rele…
Browse files Browse the repository at this point in the history
…ase branch (#314)

* New version string for develop branch (#312)

* bug/crash-in-patch-entity-attrs-when-relationship-without-object (#313)

* Implemented attribute check in incoming payload data for PATCH /entities/*/attrs - avoided a crash

* Fixed a stupid mistake

* new alpha bugfix number: 0.1.1
  • Loading branch information
kzangeli authored Jan 17, 2020
1 parent 095b691 commit 464374d
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/lib/orionld/common/orionldState.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extern "C"
//
// ORIONLD_VERSION -
//
#define ORIONLD_VERSION "v0.1.0-alpha"
#define ORIONLD_VERSION "v0.1.1-alpha"



Expand Down
109 changes: 108 additions & 1 deletion src/lib/orionld/serviceRoutines/orionldPatchEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern "C"
#include "orionld/common/orionldErrorResponse.h" // orionldErrorResponseCreate
#include "orionld/common/OrionldConnection.h" // orionldState
#include "orionld/common/SCOMPARE.h" // SCOMPAREx
#include "orionld/common/CHECK.h" // DUPLICATE_CHECK, STRING_CHECK, ...
#include "orionld/context/orionldContextItemExpand.h" // orionldContextItemExpand
#include "orionld/context/orionldContextValueExpand.h" // orionldContextValueExpand
#include "orionld/kjTree/kjTreeToContextAttribute.h" // kjTreeToContextAttribute
Expand All @@ -49,6 +50,95 @@ extern "C"



// ----------------------------------------------------------------------------
//
// attributeCheck -
//
// FIXME - move to separate module - should be used also for:
// * POST /entities/*/attrs
// * PATCH /entities/*/attrs
// * etc
//
bool attributeCheck(ConnectionInfo* ciP, KjNode* attrNodeP, char** titleP, char** detailP)
{
if (attrNodeP->type != KjObject)
{
*titleP = (char*) "Invalid JSON Type";
*detailP = (char*) "Attribute must be an object";

return false;
}

KjNode* typeP = NULL;
KjNode* valueP = NULL;
KjNode* objectP = NULL;
int attrType = 0; // 1: Property, 2: Relationship, 3: GeoProperty, 4: TemporalProperty

for (KjNode* nodeP = attrNodeP->value.firstChildP; nodeP != NULL; nodeP = nodeP->next)
{
if (strcmp(nodeP->name, "type") == 0)
{
DUPLICATE_CHECK(typeP, "type", nodeP);
STRING_CHECK(typeP, "type");

if (strcmp(typeP->value.s, "Property") == 0) attrType = 1;
else if (strcmp(typeP->value.s, "Relationship") == 0) attrType = 2;
else if (strcmp(typeP->value.s, "GeoProperty") == 0) attrType = 3;
else if (strcmp(typeP->value.s, "TemporalProperty") == 0) attrType = 4;
else
{
*titleP = (char*) "Invalid Value of Attribute Type";
*detailP = typeP->value.s;

return false;
}
}
else if (strcmp(nodeP->name, "value") == 0)
{
DUPLICATE_CHECK(valueP, "value", nodeP);
}
else if (strcmp(nodeP->name, "object") == 0)
{
DUPLICATE_CHECK(objectP, "object", nodeP);
}
}

if (typeP == NULL)
{
*titleP = (char*) "Mandatory field missing";
*detailP = (char*) "attribute type";

return false;
}

if (attrType == 2) // 2 == Relationship
{
// Relationships MUST have an "object"
if (objectP == NULL)
{
*titleP = (char*) "Mandatory field missing";
*detailP = (char*) "Relationship object";

return false;
}
}
else
{
// Properties MUST have a "value"
if (valueP == NULL)
{
*titleP = (char*) "Mandatory field missing";
*detailP = (char*) "Property value";

return false;
}
}

return true;
}



// ----------------------------------------------------------------------------
//
// orionldPatchEntity -
Expand Down Expand Up @@ -78,7 +168,6 @@ bool orionldPatchEntity(ConnectionInfo* ciP)
return false;
}


// Is the payload not a JSON object?
if (orionldState.requestTree->type != KjObject)
{
Expand All @@ -95,13 +184,15 @@ bool orionldPatchEntity(ConnectionInfo* ciP)
return false;
}

// Get the Entity from the database
if ((currentEntityTree = dbEntityLookup(entityId)) == NULL)
{
ciP->httpStatusCode = SccNotFound;
orionldErrorResponseCreate(OrionldBadRequestData, "Entity does not exist", entityId);
return false;
}


//
// o Make sure the attributes to be patched exist. If not - ignore!
// o Expand attribute values if the @context says they should be expanded
Expand All @@ -119,6 +210,22 @@ bool orionldPatchEntity(ConnectionInfo* ciP)

next = attrNodeP->next;

//
// Is the incoming payload correct?
// 1. All attributes must have a type
// 2. All attributes must have a value/object
//
char* title;
char* detail;

if (attributeCheck(ciP, attrNodeP, &title, &detail) == false)
{
LM_E(("attributeCheck: %s: %s", title, detail));
orionldErrorResponseCreate(OrionldBadRequestData, title, detail);
ciP->httpStatusCode = SccBadRequest;
return false;
}

if ((strncmp(attrNodeP->name, "http://", 7) == 0) || (strncmp(attrNodeP->name, "https://", 8) == 0))
attrName = attrNodeP->name;
else
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Copyright 2019 FIWARE Foundation e.V.
#
# This file is part of Orion-LD Context Broker.
#
# Orion-LD Context Broker is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# Orion-LD Context Broker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
# General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/.
#
# For those usages not covered by this license please contact with
# orionld at fiware dot org

# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh

--NAME--
Crash in PATCH /entities/*/attrs when relationship without object

--SHELL-INIT--
export BROKER=orionld
dbInit CB
brokerStart CB

--SHELL--

#
# 01. Create an entity urn:ngsi-ld:T:001, with a relationship R1
# 02. Update the attribute R1 using PATCH /ngsi-ld/v1/entities/urn:ngsi-ld:T:001/attrs, but without 'object' - see error and make sure no crash
#

echo "01. Create an entity urn:ngsi-ld:T:001, with a relationship R1"
echo "=============================================================="
payload='{
"id": "urn:ngsi-ld:T:001",
"type": "T",
"R1": {
"type": "Relationship",
"object": "http://a.b.c/hola"
}
}'
orionCurl --url /ngsi-ld/v1/entities -X POST --payload "$payload"
echo
echo


echo "02. Update the attribute R1 using PATCH /ngsi-ld/v1/entities/urn:ngsi-ld:T:001/attrs, but without 'object' - see error and make sure no crash"
echo "============================================================================================================================================="
payload='{
"R1": {
"type": "Relationship",
"value": "http://a.b.c/hola2"
}
}'
orionCurl --url /ngsi-ld/v1/entities/urn:ngsi-ld:T:001/attrs -X PATCH --payload "$payload"
echo
echo


--REGEXPECT--
01. Create an entity urn:ngsi-ld:T:001, with a relationship R1
==============================================================
HTTP/1.1 201 Created
Content-Length: 0
Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"
Location: /ngsi-ld/v1/entities/urn:ngsi-ld:T:001
Date: REGEX(.*)



02. Update the attribute R1 using PATCH /ngsi-ld/v1/entities/urn:ngsi-ld:T:001/attrs, but without 'object' - see error and make sure no crash
=============================================================================================================================================
HTTP/1.1 400 Bad Request
Content-Length: 126
Content-Type: application/json
Date: REGEX(.*)

{
"detail": "Relationship object",
"title": "Mandatory field missing",
"type": "https://uri.etsi.org/ngsi-ld/errors/BadRequestData"
}


--TEARDOWN--
brokerStop CB
dbDrop CB

0 comments on commit 464374d

Please sign in to comment.