mirror of https://gitee.com/bigwinds/arangodb
issue #1409: fix NUL-byte handling
This commit is contained in:
parent
c4f5f69b01
commit
ead2ee47e7
|
@ -1012,7 +1012,7 @@ AstNode* Ast::createNodeValueString (char const* value,
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*value == '\0') {
|
if (length == 0) {
|
||||||
// performance optimization:
|
// performance optimization:
|
||||||
// return a pointer to the singleton empty string node
|
// return a pointer to the singleton empty string node
|
||||||
// note: these nodes are never registered nor freed
|
// note: these nodes are never registered nor freed
|
||||||
|
|
|
@ -485,6 +485,87 @@ function AttributesSuite () {
|
||||||
assertEqual("foo\u0001bar\u0000baz", result[0].abc);
|
assertEqual("foo\u0001bar\u0000baz", result[0].abc);
|
||||||
assertEqual("\u0000test\u0000test", result[0].def);
|
assertEqual("\u0000test\u0000test", result[0].def);
|
||||||
assertEqual("abc\u0000", result[0]["123"]);
|
assertEqual("abc\u0000", result[0]["123"]);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test values containing NULL bytes
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testNullBytesValues : function () {
|
||||||
|
var docs = [
|
||||||
|
{ value: "\u0000zero\u0000", _key: "first" },
|
||||||
|
{ value: "\u0000\r\nnew line", _key: "second" },
|
||||||
|
{ value: "\u0000zero", _key: "third" },
|
||||||
|
{ value: "0\r\nxxx", _key: "fourth" }
|
||||||
|
];
|
||||||
|
|
||||||
|
docs.forEach(function(doc) {
|
||||||
|
c.insert(doc);
|
||||||
|
});
|
||||||
|
|
||||||
|
// test return value of document()
|
||||||
|
docs.forEach(function(doc) {
|
||||||
|
var d = c.document(doc._key);
|
||||||
|
assertEqual(doc.value, d.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// test return value of AQL, using literals
|
||||||
|
docs.forEach(function(doc) {
|
||||||
|
var result = db._query("FOR doc IN @@collection FILTER doc.value == " +
|
||||||
|
JSON.stringify(doc.value) + " RETURN doc", {
|
||||||
|
"@collection" : c.name()
|
||||||
|
}).toArray();
|
||||||
|
|
||||||
|
assertEqual(1, result.length, doc);
|
||||||
|
assertEqual(doc.value, result[0].value);
|
||||||
|
assertEqual(doc._key, result[0]._key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// test return value of AQL, using bind parameters
|
||||||
|
docs.forEach(function(doc) {
|
||||||
|
var result = db._query("FOR doc IN @@collection FILTER doc.value == @value RETURN doc", {
|
||||||
|
"@collection" : c.name(),
|
||||||
|
value: doc.value
|
||||||
|
}).toArray();
|
||||||
|
|
||||||
|
assertEqual(1, result.length, doc);
|
||||||
|
assertEqual(doc.value, result[0].value);
|
||||||
|
assertEqual(doc._key, result[0]._key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// test return value of AQL
|
||||||
|
var result;
|
||||||
|
result = db._query("FOR doc IN @@collection FILTER SUBSTRING(doc.value, 0, 5) == @value RETURN doc._key", {
|
||||||
|
"@collection" : c.name(),
|
||||||
|
value: "\u0000zero"
|
||||||
|
}).toArray().sort();
|
||||||
|
|
||||||
|
assertEqual(2, result.length);
|
||||||
|
assertEqual([ "first", "third" ], result);
|
||||||
|
|
||||||
|
result = db._query("FOR doc IN @@collection FILTER SUBSTRING(doc.value, 0, 6) == @value RETURN doc._key", {
|
||||||
|
"@collection" : c.name(),
|
||||||
|
value: "\u0000zero\u0000"
|
||||||
|
}).toArray();
|
||||||
|
|
||||||
|
assertEqual(1, result.length);
|
||||||
|
assertEqual([ "first" ], result);
|
||||||
|
|
||||||
|
result = db._query("FOR doc IN @@collection FILTER SUBSTRING(doc.value, 0, 1) == " +
|
||||||
|
JSON.stringify("\0") + " RETURN doc._key", {
|
||||||
|
"@collection" : c.name()
|
||||||
|
}).toArray().sort();
|
||||||
|
|
||||||
|
assertEqual(3, result.length);
|
||||||
|
assertEqual([ "first", "second", "third" ], result);
|
||||||
|
|
||||||
|
result = db._query("FOR doc IN @@collection FILTER SUBSTRING(doc.value, 0, 1) == @value RETURN doc._key", {
|
||||||
|
"@collection" : c.name(),
|
||||||
|
value: "\0",
|
||||||
|
}).toArray().sort();
|
||||||
|
|
||||||
|
assertEqual(3, result.length);
|
||||||
|
assertEqual([ "first", "second", "third" ], result);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -244,14 +244,18 @@ int TRI_CompareValuesJson (TRI_json_t const* lhs,
|
||||||
case TRI_JSON_STRING_REFERENCE: {
|
case TRI_JSON_STRING_REFERENCE: {
|
||||||
// same for STRING and STRING_REFERENCE
|
// same for STRING and STRING_REFERENCE
|
||||||
int res;
|
int res;
|
||||||
|
size_t const nl = lhs->_value._string.length - 1;
|
||||||
|
size_t const nr = rhs->_value._string.length - 1;
|
||||||
if (useUTF8) {
|
if (useUTF8) {
|
||||||
res = TRI_compare_utf8(lhs->_value._string.data,
|
res = TRI_compare_utf8(lhs->_value._string.data,
|
||||||
lhs->_value._string.length - 1,
|
nl,
|
||||||
rhs->_value._string.data,
|
rhs->_value._string.data,
|
||||||
rhs->_value._string.length - 1);
|
nr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = strcmp(lhs->_value._string.data, rhs->_value._string.data);
|
// beware of strings containing NUL bytes
|
||||||
|
size_t len = nl < nr ? nl : nr;
|
||||||
|
res = memcmp(lhs->_value._string.data, rhs->_value._string.data, len);
|
||||||
}
|
}
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -259,8 +263,13 @@ int TRI_CompareValuesJson (TRI_json_t const* lhs,
|
||||||
else if (res > 0) {
|
else if (res > 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// res == 0
|
||||||
|
if (nl == nr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// res == 0, but different string lengths
|
||||||
|
return nl < nr ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
case TRI_JSON_ARRAY: {
|
case TRI_JSON_ARRAY: {
|
||||||
size_t const nl = TRI_LengthVector(&lhs->_value._objects);
|
size_t const nl = TRI_LengthVector(&lhs->_value._objects);
|
||||||
|
|
Loading…
Reference in New Issue