1
0
Fork 0

fixed handling of empty and reserved attribute names in documents

specifying an empty attribute name in a document may have led to segmentation faults
when the document was unpacked later.
This commit is contained in:
Jan Steemann 2013-03-20 11:48:33 +01:00
parent 609629ead1
commit 40199d64b7
12 changed files with 415 additions and 43 deletions

View File

@ -0,0 +1,163 @@
# coding: utf-8
require 'rspec'
require './arangodb.rb'
describe ArangoDB do
api = "/_api/document"
prefix = "attributes"
context "dealing with attribute names" do
before do
@cn = "UnitTestsCollectionAttributes"
ArangoDB.drop_collection(@cn)
@cid = ArangoDB.create_collection(@cn)
end
after do
ArangoDB.drop_collection(@cn)
end
################################################################################
## creates a document with an empty attribute
################################################################################
it "creates a document with an empty attribute name" do
cmd = api + "?collection=" + @cn
body = "{ \"\" : \"a\", \"foo\" : \"b\" }"
doc = ArangoDB.log_post("#{prefix}-create-empty-name", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
id = doc.parsed_response['_id']
cmd = api + "/" + id
doc = ArangoDB.log_get("#{prefix}-create-empty-name", cmd)
doc.parsed_response.should_not have_key('')
doc.parsed_response.should have_key('foo')
end
################################################################################
## queries a document with an empty attribute
################################################################################
it "queries a document with an empty attribute name" do
cmd = api + "?collection=" + @cn
body = "{ \"\" : \"a\", \"foo\" : \"b\" }"
doc = ArangoDB.log_post("#{prefix}-query-empty-name", cmd, :body => body)
doc.code.should eq(201)
doc.parsed_response['error'].should eq(false)
cmd = "/_api/simple/all"
body = "{ \"collection\" : \"" + @cn + "\" }"
doc = ArangoDB.log_put("#{prefix}-query-empty-name", cmd, :body => body)
documents = doc.parsed_response['result']
documents.length.should eq(1)
documents[0].should_not have_key('')
documents[0].should have_key('foo')
end
################################################################################
## creates a document with reserved attribute names
################################################################################
it "creates a document with reserved attribute names" do
cmd = api + "?collection=" + @cn
body = "{ \"_rev\" : \"99\", \"foo\" : \"002\", \"_id\" : \"meow\", \"_from\" : \"a\", \"_to\" : \"b\", \"_test\" : \"c\", \"meow\" : \"d\" }"
doc = ArangoDB.log_post("#{prefix}-create-reserved-names", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
id = doc.parsed_response['_id']
cmd = api + "/" + id
doc = ArangoDB.log_get("#{prefix}-create-reserved-names", cmd)
doc.parsed_response['_id'].should eq(id)
doc.parsed_response['_rev'].should_not eq('99')
doc.parsed_response.should_not have_key('_from')
doc.parsed_response.should_not have_key('_to')
doc.parsed_response.should_not have_key('_test')
doc.parsed_response.should have_key('meow')
doc.parsed_response['meow'].should eq('d')
doc.parsed_response['foo'].should eq('002')
end
################################################################################
## nested attribute names
################################################################################
it "creates a document with nested attribute names" do
cmd = api + "?collection=" + @cn
body = "{ \"a\" : \"1\", \"b\" : { \"b\" : \"2\" , \"a\" : \"3\", \"\": \"4\", \"_from\": \"5\", \"c\" : 6 } }"
doc = ArangoDB.log_post("#{prefix}-create-duplicate-names", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
id = doc.parsed_response['_id']
cmd = api + "/" + id
doc = ArangoDB.log_get("#{prefix}-create-empty-name", cmd)
doc.parsed_response.should have_key('a')
doc.parsed_response['a'].should eq('1')
doc.parsed_response.should have_key('b')
doc.parsed_response['b'].should_not have_key('')
doc.parsed_response['b'].should_not have_key('_from')
doc.parsed_response['b'].should have_key('b')
doc.parsed_response['b'].should have_key('a')
doc.parsed_response['b'].should have_key('c')
doc.parsed_response['b'].should eq({ "b" => "2", "a" => "3", "c" => 6 })
end
################################################################################
## duplicate attribute names
################################################################################
it "creates a document with duplicate attribute names" do
cmd = api + "?collection=" + @cn
body = "{ \"a\" : \"1\", \"b\" : \"2\", \"a\" : \"3\" }"
doc = ArangoDB.log_post("#{prefix}-create-duplicate-names", cmd, :body => body)
doc.code.should eq(400)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(400)
doc.parsed_response['errorNum'].should eq(600)
end
################################################################################
## nested duplicate attribute names
################################################################################
it "creates a document with nested duplicate attribute names" do
cmd = api + "?collection=" + @cn
body = "{ \"a\" : \"1\", \"b\" : { \"b\" : \"2\" , \"c\" : \"3\", \"b\": \"4\" } }"
doc = ArangoDB.log_post("#{prefix}-create-duplicate-names-nested", cmd, :body => body)
doc.code.should eq(400)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(400)
doc.parsed_response['errorNum'].should eq(600)
end
end
end

View File

@ -4,6 +4,7 @@ test -d logs || mkdir logs
rspec --color --format d \
api-http-spec.rb \
api-admin-spec.rb \
api-attributes-spec.rb \
api-batch-spec.rb \
api-collection-spec.rb \
api-graph-spec.rb \

View File

@ -210,6 +210,7 @@ endif
################################################################################
SHELL_COMMON = @top_srcdir@/js/common/tests/shell-require.js \
@top_srcdir@/js/common/tests/shell-attributes.js \
@top_srcdir@/js/common/tests/shell-document.js \
@top_srcdir@/js/common/tests/shell-edge.js \
@top_srcdir@/js/common/tests/shell-database.js \

View File

@ -1000,6 +1000,7 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
TRI_primary_collection_t* primary = trx->primaryCollection();
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper);
if (! holder.registerShapedJson(primary->_shaper, shaped)) {
return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(),
@ -1999,7 +2000,7 @@ static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION,
"<list> must be a list")));
}
// extract objects
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(argv[0]);
TRI_json_t* json = TRI_ObjectToJson(array);
@ -6006,10 +6007,11 @@ static v8::Handle<v8::Value> MapGetShapedJson (v8::Local<v8::String> name,
TRI_primary_collection_t* collection = barrier->_container->_collection;
// convert the JavaScript string to a string
string key = TRI_ObjectToString(name);
const string key = TRI_ObjectToString(name);
if (key == "") {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ARANGO_ILLEGAL_NAME, "name must not be empty")));
if (key.size() == 0) {
// we must not throw a v8 exception here because this will cause follow up errors
return scope.Close(v8::Handle<v8::Value>());
}
if (TRI_IsSystemCollectionName(key.c_str())) {
@ -6020,9 +6022,6 @@ static v8::Handle<v8::Value> MapGetShapedJson (v8::Local<v8::String> name,
TRI_shaper_t* shaper = collection->_shaper;
TRI_shape_pid_t pid = shaper->findAttributePathByName(shaper, key.c_str());
// TRI_shape_sid_t sid;
// TRI_EXTRACT_SHAPE_IDENTIFIER_MARKER(sid, marker);
TRI_shaped_json_t document;
TRI_EXTRACT_SHAPED_JSON_MARKER(document, marker);
@ -6040,7 +6039,8 @@ static v8::Handle<v8::Value> MapGetShapedJson (v8::Local<v8::String> name,
}
}
else {
return scope.Close(v8::ThrowException(v8::String::New("cannot extract attribute")));
// we must not throw a v8 exception here because this will cause follow up errors
return scope.Close(v8::Handle<v8::Value>());
}
}

View File

@ -193,6 +193,10 @@ static int TraditionalGenerate (TRI_key_generator_t* const generator,
// user key is too long
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
}
else if (userKeyLength == 0) {
// user key is empty
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
}
// validate user-supplied key
if (regexec(&data->_regex, userKey, 0, NULL, 0) != 0) {

View File

@ -483,7 +483,7 @@
////////////////////////////////////////////////////////////////////////////////
var quoteSingleJsonCharacter = function (c) {
if (characterQuoteCache.hasOwnProperty[c]) {
if (characterQuoteCache.hasOwnProperty(c)) {
return characterQuoteCache[c];
}

View File

@ -483,7 +483,7 @@
////////////////////////////////////////////////////////////////////////////////
var quoteSingleJsonCharacter = function (c) {
if (characterQuoteCache.hasOwnProperty[c]) {
if (characterQuoteCache.hasOwnProperty(c)) {
return characterQuoteCache[c];
}

View File

@ -0,0 +1,188 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief test attribute naming
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var arangodb = require("org/arangodb");
var db = arangodb.db;
var wait = require("internal").wait;
// -----------------------------------------------------------------------------
// --SECTION-- attributes
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test attributes
////////////////////////////////////////////////////////////////////////////////
function AttributesSuite () {
var cn = "UnitTestsCollectionAttributes";
var c = null;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
db._drop(cn);
c = db._create(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
c.unload();
c.drop();
c = null;
wait(0.0);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief no attributes
////////////////////////////////////////////////////////////////////////////////
testNoAttributes : function () {
var doc = { };
var d1 = c.save(doc);
var d2 = c.document(d1._id);
delete d1.error;
assertEqual(d1, d2);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief empty attribute name
////////////////////////////////////////////////////////////////////////////////
testEmptyAttribute : function () {
var doc = { "" : "foo" };
var d1 = c.save(doc);
var d2 = c.document(d1._id);
delete d1.error;
var i;
for (i in d2) {
if (d2.hasOwnProperty(i)) {
assertTrue(i !== "");
}
}
assertEqual(d1, d2);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief query empty attribute name
////////////////////////////////////////////////////////////////////////////////
testQueryEmptyAttribute : function () {
var doc = { "" : "foo" };
c.save(doc);
var docs = c.toArray();
assertEqual(1, docs.length);
var d = docs[0];
var i;
for (i in d) {
if (d.hasOwnProperty(i)) {
assertTrue(i !== "");
}
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief reserved attribute names
////////////////////////////////////////////////////////////////////////////////
testReservedAttributes : function () {
var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false };
var d1 = c.save(doc);
var d2 = c.document(d1._id);
assertEqual("meow", d1._key);
assertEqual("meow", d2._key);
assertEqual(cn + "/meow", d1._id);
assertEqual(cn + "/meow", d2._id);
assertEqual(d1._rev, d2._rev);
// user specified _rev value must have been ignored
assertTrue(d1._rev !== "99");
// test attributes
var i;
for (i in d2) {
if (d2.hasOwnProperty(i)) {
assertTrue(i !== "_from" && i !== "_to" && i !== "_test");
}
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief attribute name with special chars
////////////////////////////////////////////////////////////////////////////////
testSpecialAttributes : function () {
var doc = { "-meow-" : 1, "mötör" : 2, " " : 3, "\t" : 4, "\r" : 5, "\n" : 6 };
var d1 = c.save(doc);
var d2 = c.document(d1._id);
assertEqual(1, d2["-meow-"]);
assertEqual(2, d2["mötör"]);
assertEqual(3, d2[" "]);
assertEqual(4, d2["\t"]);
assertEqual(5, d2["\r"]);
assertEqual(6, d2["\n"]);
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- main
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(AttributesSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -89,7 +89,6 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@ -213,11 +212,6 @@ typedef void* yyscan_t;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
@ -240,6 +234,11 @@ typedef size_t yy_size_t;
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
@ -257,7 +256,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
yy_size_t yy_n_chars;
int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
@ -336,7 +335,7 @@ static void tri_jsp__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscann
YY_BUFFER_STATE tri_jsp__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE tri_jsp__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE tri_jsp__scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
YY_BUFFER_STATE tri_jsp__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *tri_jsp_alloc (yy_size_t ,yyscan_t yyscanner );
void *tri_jsp_realloc (void *,yy_size_t ,yyscan_t yyscanner );
@ -387,7 +386,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyleng = (size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
@ -566,8 +565,8 @@ struct yyguts_t
size_t yy_buffer_stack_max; /**< capacity of stack. */
YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
char yy_hold_char;
yy_size_t yy_n_chars;
yy_size_t yyleng_r;
int yy_n_chars;
int yyleng_r;
char *yy_c_buf_p;
int yy_init;
int yy_start;
@ -614,7 +613,7 @@ FILE *tri_jsp_get_out (yyscan_t yyscanner );
void tri_jsp_set_out (FILE * out_str ,yyscan_t yyscanner );
yy_size_t tri_jsp_get_leng (yyscan_t yyscanner );
int tri_jsp_get_leng (yyscan_t yyscanner );
char *tri_jsp_get_text (yyscan_t yyscanner );
@ -673,7 +672,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
yy_size_t n; \
int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@ -1129,7 +1128,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
yy_size_t num_to_read =
int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@ -1143,7 +1142,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( b->yy_is_our_buffer )
{
yy_size_t new_size = b->yy_buf_size * 2;
int new_size = b->yy_buf_size * 2;
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
@ -1174,7 +1173,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
yyg->yy_n_chars, num_to_read );
yyg->yy_n_chars, (int) num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@ -1299,7 +1298,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@ -1323,7 +1322,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
case EOB_ACT_END_OF_FILE:
{
if ( tri_jsp_wrap(yyscanner ) )
return 0;
return EOF;
if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
@ -1585,7 +1584,7 @@ void tri_jsp_pop_buffer_state (yyscan_t yyscanner)
*/
static void tri_jsp_ensure_buffer_stack (yyscan_t yyscanner)
{
yy_size_t num_to_alloc;
int num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@ -1683,11 +1682,12 @@ YY_BUFFER_STATE tri_jsp__scan_string (yyconst char * yystr , yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE tri_jsp__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
YY_BUFFER_STATE tri_jsp__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n, i;
yy_size_t n;
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
@ -1797,7 +1797,7 @@ FILE *tri_jsp_get_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
yy_size_t tri_jsp_get_leng (yyscan_t yyscanner)
int tri_jsp_get_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@ -2184,7 +2184,7 @@ static TRI_json_t* ParseArray (yyscan_t scanner) {
// do proper unescaping
name = TRI_UnescapeUtf8StringZ(yyextra._memoryZone, yytext + 1, nameLen, &outLength);
nameLen = outLength;
}
else if (c == STRING_CONSTANT_ASCII) {
// ASCII-only attribute name

View File

@ -286,7 +286,7 @@ static TRI_json_t* ParseArray (yyscan_t scanner) {
// do proper unescaping
name = TRI_UnescapeUtf8StringZ(yyextra._memoryZone, yytext + 1, nameLen, &outLength);
nameLen = outLength;
}
else if (c == STRING_CONSTANT_ASCII) {
// ASCII-only attribute name

View File

@ -310,6 +310,8 @@ static int WeightShapeType (TRI_shape_type_t type) {
case TRI_SHAPE_HOMOGENEOUS_LIST: return 900;
}
LOG_ERROR("invalid shape type: %d\n", (int) type);
assert(false);
return 0;
}
@ -780,8 +782,8 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, T
char* ptr;
// sanity checks
assert(json->_type == TRI_JSON_ARRAY);
assert(json->_value._objects._length % 2 == 0);
TRI_ASSERT_DEBUG(json->_type == TRI_JSON_ARRAY);
TRI_ASSERT_DEBUG(json->_value._objects._length % 2 == 0);
// number of attributes
n = json->_value._objects._length / 2;
@ -805,6 +807,17 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, T
key = TRI_AtVector(&json->_value._objects, 2 * i);
val = TRI_AtVector(&json->_value._objects, 2 * i + 1);
TRI_ASSERT_DEBUG(key != NULL);
TRI_ASSERT_DEBUG(val != NULL);
if (key->_value._string.data == NULL ||
key->_value._string.length == 1 ||
key->_value._string.data[0] == '_') {
// empty or reserved attribute name
p--;
continue;
}
// first find an identifier for the name
p->_aid = shaper->findAttributeName(shaper, key->_value._string.data);
@ -841,6 +854,9 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, T
// add variable offset table size
total += (v + 1) * sizeof(TRI_shape_size_t);
// now adjust n because we might have excluded empty attributes
n = f + v;
// now sort the shape entries
TRI_SortShapeValues(values, n);

View File

@ -289,8 +289,6 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
return false;
}
memset(values, 0, sizeof(TRI_shape_value_t) * n);
total = 0;
e = values + n;
@ -592,7 +590,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
// first find an identifier for the name
TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);
if (*keyStr == 0) {
if (*keyStr == 0 || keyStr.length() == 0) {
--p;
continue;
}
@ -789,13 +787,12 @@ static bool FillShapeValueJson (TRI_shaper_t* shaper,
return FillShapeValueNull(shaper, dst);
}
}
seenObjects.push_back(o);
}
else {
seenHashes.insert(hash);
seenObjects.push_back(o);
}
seenObjects.push_back(o);
}
if (json->IsNull()) {
@ -1439,6 +1436,7 @@ TRI_json_t* TRI_ObjectToJson (v8::Handle<v8::Value> parameter) {
const uint32_t n = arrayParameter->Length();
TRI_json_t* listJson = TRI_CreateList2Json(TRI_UNKNOWN_MEM_ZONE, (const size_t) n);
if (listJson != 0) {
for (uint32_t j = 0; j < n; ++j) {
v8::Handle<v8::Value> item = arrayParameter->Get(j);
@ -1458,9 +1456,10 @@ TRI_json_t* TRI_ObjectToJson (v8::Handle<v8::Value> parameter) {
const uint32_t n = names->Length();
TRI_json_t* arrayJson = TRI_CreateArray2Json(TRI_UNKNOWN_MEM_ZONE, (const size_t) n);
if (arrayJson != 0) {
for (uint32_t j = 0; j < n; ++j) {
v8::Handle<v8::Value> key = names->Get(j);
v8::Handle<v8::Value> key = names->Get(j);
v8::Handle<v8::Value> item = arrayParameter->Get(key);
TRI_json_t* result = TRI_ObjectToJson(item);