Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com>2021-05-07 10:46:13 +0300
committerDmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com>2021-05-07 10:46:13 +0300
commit42036f98c37f8cfe6f945ccdb15e3da5118fe90b (patch)
tree511c4eb6d40c4817148195a4a45b8fa4d4643fc7 /src
parent72a1333026bbe002da23ed93486bd2ea94ffd397 (diff)
parent0059d93568dc0b5bfb0618720a3706ffa06878e7 (diff)
........S. [ZBXNEXT-6544] fixed merge conflict
Diffstat (limited to 'src')
-rw-r--r--src/libs/zbxeval/execute.c321
-rw-r--r--src/libs/zbxeval/parse.c2
-rw-r--r--src/libs/zbxserver/evalfunc2.c7
3 files changed, 319 insertions, 11 deletions
diff --git a/src/libs/zbxeval/execute.c b/src/libs/zbxeval/execute.c
index a82608f12b5..cb1249d8036 100644
--- a/src/libs/zbxeval/execute.c
+++ b/src/libs/zbxeval/execute.c
@@ -130,6 +130,13 @@ static int eval_execute_op_unary(const zbx_eval_context_t *ctx, const zbx_eval_t
return FAIL;
}
+ if (FP_ZERO != fpclassify(value) && FP_NORMAL != fpclassify(value))
+ {
+ *error = zbx_dsprintf(*error, "calculation resulted in NaN or Infinity at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
zbx_variant_clear(right);
zbx_variant_set_dbl(right, value);
@@ -373,6 +380,14 @@ static int eval_execute_op_binary(const zbx_eval_context_t *ctx, const zbx_eval_
value = left->data.dbl / right->data.dbl;
break;
}
+
+ if (FP_ZERO != fpclassify(value) && FP_NORMAL != fpclassify(value))
+ {
+ *error = zbx_dsprintf(*error, "calculation resulted in NaN or Infinity at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
finish:
zbx_variant_clear(left);
zbx_variant_clear(right);
@@ -559,13 +574,14 @@ int eval_compare_token(const zbx_eval_context_t *ctx, const zbx_strloc_t *loc, c
* return value. *
* *
******************************************************************************/
-static void eval_function_return(int args_num, zbx_variant_t *value, zbx_vector_var_t *output)
+static void eval_function_return(zbx_uint32_t args_num, zbx_variant_t *value, zbx_vector_var_t *output)
{
int i;
- for (i = output->values_num - args_num; i < output->values_num; i++)
+ for (i = output->values_num - (int)args_num; i < output->values_num; i++)
zbx_variant_clear(&output->values[i]);
- output->values_num -= args_num;
+
+ output->values_num -= (int)args_num;
zbx_vector_var_append_ptr(output, value);
}
@@ -2200,11 +2216,11 @@ out:
* *
* Purpose: evaluate function by calling custom callback (if configured) *
* *
- * Parameters: ctx - [IN] the evaluation context *
- * token - [IN] the function token *
- * functio_cb - [IN] the callback function *
- * output - [IN/OUT] the output value stack *
- * error - [OUT] the error message in the case of failure *
+ * Parameters: ctx - [IN] the evaluation context *
+ * token - [IN] the function token *
+ * function_cb - [IN] the callback function *
+ * output - [IN/OUT] the output value stack *
+ * error - [OUT] the error message in the case of failure *
* *
* Return value: SUCCEED - the function was executed successfully *
* FAIL - otherwise *
@@ -2236,6 +2252,239 @@ static int eval_execute_cb_function(const zbx_eval_context_t *ctx, const zbx_eva
return SUCCEED;
}
+#define ZBX_MATH_CONST_PI 3.141592653589793238463
+#define ZBX_MATH_CONST_E 2.7182818284590452354
+#define ZBX_MATH_RANDOM 0
+
+static double eval_math_func_degrees(double radians)
+{
+ return radians * (180.0 / ZBX_MATH_CONST_PI);
+}
+
+static double eval_math_func_radians(double degrees)
+{
+ return degrees * (ZBX_MATH_CONST_PI / 180);
+}
+
+static double eval_math_func_cot(double x)
+{
+ return cos(x) / sin(x);
+}
+
+static double eval_math_func_signum(double x)
+{
+ if (0 > x)
+ return -1;
+
+ if (0 == x)
+ return 0;
+
+ return 1;
+}
+
+/******************************************************************************
+ * *
+ * Function: eval_execute_math_function_single_param *
+ * *
+ * Purpose: evaluate mathematical function by calling passed function *
+ * with 1 double argument *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * token - [IN] the function token *
+ * output - [IN/OUT] the output value stack *
+ * error - [OUT] the error message in the case of failure *
+ * func - [IN] the pointer to math function *
+ * *
+ * Return value: SUCCEED - function evaluation succeeded *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int eval_execute_math_function_single_param(const zbx_eval_context_t *ctx, const zbx_eval_token_t *token,
+ zbx_vector_var_t *output, char **error, double (*func)(double))
+{
+ int ret;
+ double result;
+ zbx_variant_t *arg, value;
+
+ if (1 != token->opt)
+ {
+ *error = zbx_dsprintf(*error, "invalid number of arguments for function at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
+ if (UNKNOWN != (ret = eval_prepare_math_function_args(ctx, token, output, error)))
+ return ret;
+
+ arg = &output->values[output->values_num - 1];
+
+ if (((log == func || log10 == func) && 0 >= arg->data.dbl) || (sqrt == func && 0 > arg->data.dbl) ||
+ (eval_math_func_cot == func && 0 == arg->data.dbl))
+ {
+ *error = zbx_dsprintf(*error, "invalid argument for function at \"%s\"",
+ ctx->expression + token->loc.l);
+
+ return FAIL;
+ }
+
+ result = func(arg->data.dbl);
+
+ if (FP_ZERO != fpclassify(result) && FP_NORMAL != fpclassify(result))
+ {
+ *error = zbx_dsprintf(*error, "calculation resulted in NaN or Infinity at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
+ zbx_variant_set_dbl(&value, result);
+
+ eval_function_return(token->opt, &value, output);
+
+ return SUCCEED;
+}
+
+static double eval_math_func_round(double n, double decimal_points)
+{
+ double multiplier;
+
+ multiplier = pow(10.0, decimal_points);
+
+ return round(n * multiplier ) / multiplier;
+}
+
+static double eval_math_func_truncate(double n, double decimal_points)
+{
+ double multiplier = 1;
+
+ if (0 < decimal_points)
+ multiplier = pow(10, decimal_points);
+
+ if (0 > n)
+ multiplier = -multiplier;
+
+ return floor(multiplier * n) / multiplier;
+}
+
+/******************************************************************************
+ * *
+ * Function: eval_execute_math_function_double_param *
+ * *
+ * Purpose: evaluate mathematical function by calling passed function *
+ * with 2 double arguments *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * token - [IN] the function token *
+ * output - [IN/OUT] the output value stack *
+ * error - [OUT] the error message in the case of failure *
+ * func - [IN] the pointer to math function *
+ * *
+ * Return value: SUCCEED - function evaluation succeeded *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int eval_execute_math_function_double_param(const zbx_eval_context_t *ctx, const zbx_eval_token_t *token,
+ zbx_vector_var_t *output, char **error, double (*func)(double, double))
+{
+ int ret;
+ double result;
+ zbx_variant_t *arg1, *arg2, value;
+
+ if (2 != token->opt)
+ {
+ *error = zbx_dsprintf(*error, "invalid number of arguments for function at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
+ if (UNKNOWN != (ret = eval_prepare_math_function_args(ctx, token, output, error)))
+ return ret;
+
+ arg1 = &output->values[output->values_num - 2];
+ arg2 = &output->values[output->values_num - 1];
+
+ if (((eval_math_func_round == func || eval_math_func_truncate == func) && (0 > arg2->data.dbl ||
+ 0.0 != fmod(arg2->data.dbl, 1))) || (fmod == func && 0.0 == arg2->data.dbl))
+ {
+ *error = zbx_dsprintf(*error, "invalid second argument for function at \"%s\"",
+ ctx->expression + token->loc.l);
+
+ return FAIL;
+ }
+
+ if (atan2 == func && 0.0 == arg1->data.dbl && 0.0 == arg2->data.dbl)
+ {
+ *error = zbx_dsprintf(*error, "undefined result for arguments (0,0) for function 'atan2' at \"%s\"",
+ ctx->expression + token->loc.l);
+
+ return FAIL;
+ }
+
+ result = func(arg1->data.dbl, arg2->data.dbl);
+
+ if (FP_ZERO != fpclassify(result) && FP_NORMAL != fpclassify(result))
+ {
+ *error = zbx_dsprintf(*error, "calculation resulted in NaN or Infinity at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
+ zbx_variant_set_dbl(&value, result);
+
+ eval_function_return(token->opt, &value, output);
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: eval_execute_math_function_return_value *
+ * *
+ * Purpose: evaluate mathematical function that returns constant value *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * token - [IN] the function token *
+ * output - [IN/OUT] the output value stack *
+ * error - [OUT] the error message in the case of failure *
+ * value - [IN] the value to be returned *
+ * *
+ * Return value: SUCCEED - function evaluation succeeded *
+ * *
+ ******************************************************************************/
+static int eval_execute_math_return_value(const zbx_eval_context_t *ctx, const zbx_eval_token_t *token,
+ zbx_vector_var_t *output, char **error, double value)
+{
+ zbx_variant_t ret_value;
+
+ if (0 != token->opt)
+ {
+ *error = zbx_dsprintf(*error, "invalid number of arguments for function at \"%s\"",
+ ctx->expression + token->loc.l);
+ return FAIL;
+ }
+
+ if (ZBX_MATH_RANDOM == value)
+ {
+ struct timespec ts;
+
+ if (SUCCEED != clock_gettime(CLOCK_MONOTONIC, &ts))
+ {
+ *error = zbx_strdup(*error, "failed to generate seed for random number generator");
+ return FAIL;
+ }
+ else
+ {
+ srandom((unsigned int)(ts.tv_nsec ^ ts.tv_sec));
+ zbx_variant_set_dbl(&ret_value, random());
+ }
+ }
+ else
+ zbx_variant_set_dbl(&ret_value, value);
+
+ eval_function_return(0, &ret_value, output);
+
+ return SUCCEED;
+}
+
/******************************************************************************
* *
* Function: eval_execute_common_function *
@@ -2327,6 +2576,62 @@ static int eval_execute_common_function(const zbx_eval_context_t *ctx, const zbx
return eval_execute_function_trim(ctx, token, FUNCTION_OPTYPE_TRIM_RIGHT, output, error);
if (SUCCEED == eval_compare_token(ctx, &token->loc, "trim", ZBX_CONST_STRLEN("trim")))
return eval_execute_function_trim(ctx, token, FUNCTION_OPTYPE_TRIM_ALL, output, error);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "cbrt", ZBX_CONST_STRLEN("cbrt")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, cbrt);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "ceil", ZBX_CONST_STRLEN("ceil")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, ceil);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "exp", ZBX_CONST_STRLEN("exp")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, exp);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "expm1", ZBX_CONST_STRLEN("expm1")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, expm1);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "floor", ZBX_CONST_STRLEN("floor")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, floor);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "signum", ZBX_CONST_STRLEN("signum")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, eval_math_func_signum);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "degrees", ZBX_CONST_STRLEN("degrees")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, eval_math_func_degrees);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "radians", ZBX_CONST_STRLEN("radians")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, eval_math_func_radians);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "acos", ZBX_CONST_STRLEN("acos")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, acos);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "asin", ZBX_CONST_STRLEN("asin")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, asin);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "atan", ZBX_CONST_STRLEN("atan")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, atan);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "cos", ZBX_CONST_STRLEN("cos")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, cos);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "cosh", ZBX_CONST_STRLEN("cosh")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, cosh);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "cot", ZBX_CONST_STRLEN("cot")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, eval_math_func_cot);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "sin", ZBX_CONST_STRLEN("sin")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, sin);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "sinh", ZBX_CONST_STRLEN("sinh")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, sinh);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "tan", ZBX_CONST_STRLEN("tan")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, tan);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "log", ZBX_CONST_STRLEN("log")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, log);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "log10", ZBX_CONST_STRLEN("log10")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, log10);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "sqrt", ZBX_CONST_STRLEN("sqrt")))
+ return eval_execute_math_function_single_param(ctx, token, output, error, sqrt);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "power", ZBX_CONST_STRLEN("power")))
+ return eval_execute_math_function_double_param(ctx, token, output, error, pow);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "round", ZBX_CONST_STRLEN("round")))
+ return eval_execute_math_function_double_param(ctx, token, output, error, eval_math_func_round);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "mod", ZBX_CONST_STRLEN("mod")))
+ return eval_execute_math_function_double_param(ctx, token, output, error, fmod);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "truncate", ZBX_CONST_STRLEN("truncate")))
+ return eval_execute_math_function_double_param(ctx, token, output, error, eval_math_func_truncate);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "atan2", ZBX_CONST_STRLEN("atan2")))
+ return eval_execute_math_function_double_param(ctx, token, output, error, atan2);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "pi", ZBX_CONST_STRLEN("pi")))
+ return eval_execute_math_return_value(ctx, token, output, error, ZBX_MATH_CONST_PI);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "e", ZBX_CONST_STRLEN("e")))
+ return eval_execute_math_return_value(ctx, token, output, error, ZBX_MATH_CONST_E);
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "rand", ZBX_CONST_STRLEN("rand")))
+ return eval_execute_math_return_value(ctx, token, output, error, ZBX_MATH_RANDOM);
if (NULL != ctx->common_func_cb)
return eval_execute_cb_function(ctx, token, ctx->common_func_cb, output, error);
diff --git a/src/libs/zbxeval/parse.c b/src/libs/zbxeval/parse.c
index 91b6170d4db..31ea12e5a51 100644
--- a/src/libs/zbxeval/parse.c
+++ b/src/libs/zbxeval/parse.c
@@ -566,7 +566,7 @@ static int eval_parse_function_token(zbx_eval_context_t *ctx, size_t pos, zbx_ev
{
const char *ptr = ctx->expression + pos;
- while (0 != isalpha((unsigned char)*ptr) || '_' == *ptr)
+ while (0 != isalpha((unsigned char)*ptr) || '_' == *ptr || 0 != isdigit((unsigned char)*ptr))
ptr++;
if ('(' == *ptr)
diff --git a/src/libs/zbxserver/evalfunc2.c b/src/libs/zbxserver/evalfunc2.c
index 9b0a16f26eb..24bee12b429 100644
--- a/src/libs/zbxserver/evalfunc2.c
+++ b/src/libs/zbxserver/evalfunc2.c
@@ -2391,8 +2391,11 @@ int evaluate_function2(zbx_variant_t *value, DC_ITEM *item, const char *function
int zbx_is_trigger_function(const char *name, size_t len)
{
char *functions[] = {"last", "min", "max", "avg", "sum", "percentile", "count", "nodata", "change", "find",
- "fuzzytime", "logeventid", "logseverity", "logsource", "bitand", "forecast", "timeleft",
- "trendavg", "trendcount", "trendmax", "trendmin", "trendsum",
+ "fuzzytime", "logeventid", "logseverity", "logsource", "band", "forecast", "timeleft",
+ "trendavg", "trendcount", "trendmax", "trendmin", "trendsum", "abs", "cbrt", "ceil", "exp",
+ "floor", "log", "log10", "power", "round", "rand", "signum", "sqrt", "truncate", "acos",
+ "asin", "atan", "cos", "cosh", "cot", "sin", "sinh", "tan", "degrees", "radians", "mod", "pi",
+ "e", "expm1", "atan2",
NULL};
char **ptr;