diff --git a/arangod/Ahuacatl/ahuacatl-codegen.c b/arangod/Ahuacatl/ahuacatl-codegen.c index f9758f5f9b..0191629a0f 100644 --- a/arangod/Ahuacatl/ahuacatl-codegen.c +++ b/arangod/Ahuacatl/ahuacatl-codegen.c @@ -1346,11 +1346,11 @@ static void ProcessValue (TRI_aql_codegen_js_t* const generator, const TRI_aql_node_t* const node) { TRI_aql_codegen_scope_t* scope = CurrentScope(generator); - if (!scope->_buffer) { + if (! scope->_buffer) { return; } - if (!TRI_ValueJavascriptAql(scope->_buffer, &node->_value, node->_value._type)) { + if (! TRI_ValueJavascriptAql(scope->_buffer, &node->_value, node->_value._type)) { generator->_errorCode = TRI_ERROR_OUT_OF_MEMORY; } } @@ -1401,7 +1401,7 @@ static void ProcessArrayElement (TRI_aql_codegen_js_t* const generator, const TRI_aql_node_t* const node) { TRI_aql_codegen_scope_t* scope = CurrentScope(generator); - if (!scope->_buffer) { + if (! scope->_buffer) { return; } diff --git a/arangod/Ahuacatl/ahuacatl-conversions.c b/arangod/Ahuacatl/ahuacatl-conversions.c index b2a0380a05..923e5e6bb6 100644 --- a/arangod/Ahuacatl/ahuacatl-conversions.c +++ b/arangod/Ahuacatl/ahuacatl-conversions.c @@ -29,6 +29,7 @@ #include "BasicsC/conversions.h" #include "BasicsC/json.h" +#include "BasicsC/logging.h" #include "BasicsC/string-buffer.h" #include "BasicsC/strings.h" diff --git a/arangod/Ahuacatl/ahuacatl-optimiser.c b/arangod/Ahuacatl/ahuacatl-optimiser.c index 83317e7641..d092018084 100644 --- a/arangod/Ahuacatl/ahuacatl-optimiser.c +++ b/arangod/Ahuacatl/ahuacatl-optimiser.c @@ -973,7 +973,26 @@ static TRI_aql_node_t* OptimiseUnaryArithmeticOperation (TRI_aql_context_t* cons } else if (node->_type == TRI_AQL_NODE_OPERATOR_UNARY_MINUS) { // - number => eval! - node = TRI_CreateNodeValueDoubleAql(context, - TRI_GetNumericNodeValueAql(operand)); + double value = - TRI_GetNumericNodeValueAql(operand); + + // check for result validity +#ifdef isnan + if (isnan(value)) { + LOG_TRACE("nan value detected after arithmetic optimisation"); + TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); + return NULL; + } +#endif + +#ifdef isinf + if (isinf(value)) { + LOG_TRACE("inf value detected after arithmetic optimisation"); + TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); + return NULL; + } +#endif + + node = TRI_CreateNodeValueDoubleAql(context, value); if (node == NULL) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); } @@ -1230,6 +1249,24 @@ static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* con else { value = 0.0; } + + // check for result validity + +#ifdef isnan + if (isnan(value)) { + LOG_TRACE("nan value detected after arithmetic optimisation"); + TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); + return NULL; + } +#endif + +#ifdef isinf + if (isinf(value)) { + LOG_TRACE("inf value detected after arithmetic optimisation"); + TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); + return NULL; + } +#endif node = TRI_CreateNodeValueDoubleAql(context, value); diff --git a/js/server/tests/ahuacatl-queries-simple.js b/js/server/tests/ahuacatl-queries-simple.js index 460d64248c..d7685816ea 100644 --- a/js/server/tests/ahuacatl-queries-simple.js +++ b/js/server/tests/ahuacatl-queries-simple.js @@ -752,7 +752,7 @@ function ahuacatlQuerySimpleTestSuite () { //////////////////////////////////////////////////////////////////////////////// testListIndexes: function () { - var actual, expected; + var actual; actual = getQueryResults("LET l = [ 1, 2, 3 ] RETURN l[0]"); assertEqual([ 1 ], actual); @@ -814,7 +814,7 @@ function ahuacatlQuerySimpleTestSuite () { //////////////////////////////////////////////////////////////////////////////// testNaming: function () { - var actual, expected; + var actual; actual = getQueryResults("LET a = [ 1 ] RETURN a[0]"); assertEqual([ 1 ], actual); @@ -832,6 +832,14 @@ function ahuacatlQuerySimpleTestSuite () { assertEqual([ 1 ], actual); assertEqual(errors.ERROR_ARANGO_ILLEGAL_NAME.code, getErrorCode(function() { QUERY("LET a = 1 RETURN `a b c`"); } )); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief numeric overflow +//////////////////////////////////////////////////////////////////////////////// + + testOverflow: function () { + assertEqual(errors.ERROR_QUERY_INVALID_ARITHMETIC_VALUE.code, getErrorCode(function() { QUERY("LET l = 4444444444444555555555555555555555555555555555554444333333333333333333333334444444544 RETURN l * l * l * l"); })); } }; } diff --git a/lib/BasicsC/string-buffer.c b/lib/BasicsC/string-buffer.c index 40e9a4bac5..34dd4c0f9d 100644 --- a/lib/BasicsC/string-buffer.c +++ b/lib/BasicsC/string-buffer.c @@ -876,12 +876,39 @@ int TRI_AppendSizeHexStringBuffer (TRI_string_buffer_t * self, size_t attr) { //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -/// @brief appends floating point number with 8 bits +/// @brief appends floating point number //////////////////////////////////////////////////////////////////////////////// int TRI_AppendDoubleStringBuffer (TRI_string_buffer_t * self, double attr) { int res; +// TODO: before activating this check, make it portable +// isnan and isinf macros are available in posix, and probably in C99 only +// // check for NaN +// #ifdef isnan +// if (isnan(attr)) { +// res = Reserve(self, 3); +// if (res != TRI_ERROR_NO_ERROR) { +// return res; +// } +// TRI_AppendStringStringBuffer(self, "NaN"); +// return TRI_ERROR_NO_ERROR; +// } +// #endif +// +// // check for infinity +// // if we do not enforce this check, one of the below loops might never terminate +// #ifdef isinf +// if (isinf(attr)) { +// res = Reserve(self, 3); +// if (res != TRI_ERROR_NO_ERROR) { +// return res; +// } +// TRI_AppendStringStringBuffer(self, "inf"); +// return TRI_ERROR_NO_ERROR; +// } +// #endif + res = Reserve(self, 1); if (res != TRI_ERROR_NO_ERROR) {