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
diff options
context:
space:
mode:
authorDmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com>2022-11-09 14:46:53 +0300
committerDmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com>2022-11-09 14:46:53 +0300
commitc2d82fb4a78b3e77c0f8e74b019e1363411e0589 (patch)
treefa231e37a8a3271aef18ea5fdaaa2caec4780a3c
parent3788825fefdd8501108842666221d0da0de0fc8f (diff)
parent78966773ca31e6740989eb394796b9f144944a57 (diff)
........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions
Merge in ZBX/zabbix from feature/ZBX-21616-6.2 to release/6.2 * commit '78966773ca31e6740989eb394796b9f144944a57': ........S. [ZBX-21616] fixed function description comment ........S. [ZBX-21616] got rid of ZBX_FALLTROUGH .......... [ZBX-21616] code style fix ........S. [ZBX-21616] fixed offseet calculation when replacing condition ids with values ........S. [ZBX-21616] added more optimizations to LLD filter processing ........S. [ZBX-21616] optimized .......... [ZBX-21616] added changelog .......... [ZBX-21616] added changelog ........S. [ZBX-21616] refactored and reimplemented parsing logics ........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions
-rw-r--r--ChangeLog.d/bugfix/ZBX-216161
-rw-r--r--src/zabbix_server/lld/lld.c269
2 files changed, 149 insertions, 121 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-21616 b/ChangeLog.d/bugfix/ZBX-21616
new file mode 100644
index 00000000000..fcabe90b876
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-21616
@@ -0,0 +1 @@
+........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions (dgoloscapov, wiper)
diff --git a/src/zabbix_server/lld/lld.c b/src/zabbix_server/lld/lld.c
index 2bda0af3091..0748a0109bf 100644
--- a/src/zabbix_server/lld/lld.c
+++ b/src/zabbix_server/lld/lld.c
@@ -209,6 +209,7 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const
* Parameters: jp_row - [IN] the lld data row *
* lld_macro_paths - [IN] use json path to extract from jp_row *
* condition - [IN] the lld filter condition *
+ * result - [OUT] the result of evaluation *
* info - [OUT] the warning description *
* *
* Return value: SUCCEED - the lld data passed filter evaluation *
@@ -216,41 +217,53 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const
* *
******************************************************************************/
static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macro_paths,
- const lld_condition_t *condition, char **info)
+ const lld_condition_t *condition, int *result, char **info)
{
char *value = NULL;
- int ret;
+ int ret = SUCCEED;
- if (SUCCEED == (ret = zbx_lld_macro_value_by_name(jp_row, lld_macro_paths, condition->macro, &value)))
+ if (SUCCEED == zbx_lld_macro_value_by_name(jp_row, lld_macro_paths, condition->macro, &value))
{
if (CONDITION_OPERATOR_NOT_EXIST == condition->op)
{
- ret = FAIL;
+ *result = 0;
}
- else if (CONDITION_OPERATOR_EXIST != condition->op)
+ if (CONDITION_OPERATOR_EXIST == condition->op)
+ {
+ *result = 1;
+ }
+ else
{
switch (regexp_match_ex(&condition->regexps, value, condition->regexp, ZBX_CASE_SENSITIVE))
{
case ZBX_REGEXP_MATCH:
- ret = (CONDITION_OPERATOR_REGEXP == condition->op ? SUCCEED : FAIL);
+ *result = (CONDITION_OPERATOR_REGEXP == condition->op ? 1 : 0);
break;
case ZBX_REGEXP_NO_MATCH:
- ret = (CONDITION_OPERATOR_NOT_REGEXP == condition->op ? SUCCEED : FAIL);
+ *result = (CONDITION_OPERATOR_NOT_REGEXP == condition->op ? 1 : 0);
break;
default:
+ *info = zbx_strdcatf(*info, "Cannot accurately apply filter: invalid regular "
+ "expression \"%s\".\n", condition->regexp);
ret = FAIL;
}
}
}
- else if (CONDITION_OPERATOR_NOT_EXIST == condition->op)
- {
- ret = SUCCEED;
- }
- else if (CONDITION_OPERATOR_EXIST != condition->op)
+ else
{
- *info = zbx_strdcatf(*info,
- "Cannot accurately apply filter: no value received for macro \"%s\".\n",
- condition->macro);
+ switch (condition->op)
+ {
+ case CONDITION_OPERATOR_NOT_EXIST:
+ *result = 1;
+ break;
+ case CONDITION_OPERATOR_EXIST:
+ *result = 0;
+ break;
+ default:
+ *info = zbx_strdcatf(*info, "Cannot accurately apply filter: no value received for "
+ "macro \"%s\".\n", condition->macro);
+ ret = FAIL;
+ }
}
zbx_free(value);
@@ -258,120 +271,104 @@ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx
return ret;
}
-/******************************************************************************
- * *
- * Purpose: check if the lld data passes filter evaluation by and/or rule *
- * *
- * Parameters: filter - [IN] the lld filter *
- * jp_row - [IN] the lld data row *
- * lld_macro_paths - [IN] use json path to extract from jp_row *
- * info - [OUT] the warning description *
- * *
- * Return value: SUCCEED - the lld data passed filter evaluation *
- * FAIL - otherwise *
- * *
- ******************************************************************************/
-static int filter_evaluate_and_or(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
+/****************************************************************************************
+ * *
+ * Purpose: check if the lld data passes filter evaluation by and/or/andor rules *
+ * *
+ * Parameters: filter - [IN] the lld filter *
+ * jp_row - [IN] the lld data row *
+ * lld_macro_paths - [IN] use json path to extract from jp_row *
+ * info - [OUT] the warning description *
+ * *
+ * Return value: SUCCEED - the lld data passed filter evaluation *
+ * FAIL - otherwise *
+ * *
+ ****************************************************************************************/
+static int filter_evaluate_and_or_andor(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
const zbx_vector_ptr_t *lld_macro_paths, char **info)
{
- int i, ret = SUCCEED;
- char *lastmacro = NULL;
+ int i, ret = SUCCEED, error_num = 0, res;
+ double result;
+ char *lastmacro = NULL;
+ lld_condition_t *condition;
+ char *ops[] = {NULL, "and", "or"}, error[256], *expression = NULL, *errmsg = NULL;
+ size_t expression_alloc = 0, expression_offset = 0;
+ zbx_vector_ptr_t errmsgs;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+ zbx_vector_ptr_create(&errmsgs);
+
for (i = 0; i < filter->conditions.values_num; i++)
{
- int rc;
- const lld_condition_t *condition = (lld_condition_t *)filter->conditions.values[i];
+ condition = (lld_condition_t *)filter->conditions.values[i];
- rc = filter_condition_match(jp_row, lld_macro_paths, condition, info);
- /* check if a new condition group has started */
- if (NULL == lastmacro || 0 != strcmp(lastmacro, condition->macro))
+ switch (filter->evaltype)
{
- /* if any of condition groups are false the evaluation returns false */
- if (FAIL == ret)
+ case CONDITION_EVAL_TYPE_AND_OR:
+ if (NULL == lastmacro)
+ {
+ zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, '(');
+ }
+ else if (0 != strcmp(lastmacro, condition->macro))
+ {
+ zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, ") and ");
+ }
+ else
+ zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, " or ");
+
+ lastmacro = condition->macro;
+ break;
+ case CONDITION_EVAL_TYPE_AND:
+ case CONDITION_EVAL_TYPE_OR:
+ if (0 != i)
+ {
+ zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ' ');
+ zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset,
+ ops[filter->evaltype]);
+ zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ' ');
+ }
break;
+ default:
+ *info = zbx_strdcatf(*info, "Cannot accurately apply filter: invalid condition "
+ "type \"%d\".\n", filter->evaltype);
+ goto out;
+ }
- ret = rc;
+ if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths, condition, &res, &errmsg)))
+ {
+ zbx_snprintf_alloc(&expression, &expression_alloc, &expression_offset, "%d", res);
}
else
{
- if (SUCCEED == rc)
- ret = rc;
+ zbx_snprintf_alloc(&expression, &expression_alloc, &expression_offset, ZBX_UNKNOWN_STR "%d",
+ error_num++);
+ zbx_vector_ptr_append(&errmsgs, errmsg);
+ errmsg = NULL;
}
- lastmacro = condition->macro;
- }
-
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
-
- return ret;
-}
-
-/******************************************************************************
- * *
- * Purpose: check if the lld data passes filter evaluation by and rule *
- * *
- * Parameters: filter - [IN] the lld filter *
- * jp_row - [IN] the lld data row *
- * lld_macro_paths - [IN] use json path to extract from jp_row *
- * info - [OUT] the warning description *
- * *
- * Return value: SUCCEED - the lld data passed filter evaluation *
- * FAIL - otherwise *
- * *
- ******************************************************************************/
-static int filter_evaluate_and(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
- const zbx_vector_ptr_t *lld_macro_paths, char **info)
-{
- int i, ret = SUCCEED;
-
- zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
-
- for (i = 0; i < filter->conditions.values_num; i++)
- {
- /* if any of conditions are false the evaluation returns false */
- if (SUCCEED != (ret = filter_condition_match(jp_row, lld_macro_paths,
- (lld_condition_t *)filter->conditions.values[i], info)))
+ if (filter->conditions.values_num == i + 1)
{
- break;
+ if (CONDITION_EVAL_TYPE_AND_OR == filter->evaltype)
+ zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ')');
+
+ expression_offset++;
}
}
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
-
- return ret;
-}
-
-/******************************************************************************
- * *
- * Purpose: check if the lld data passes filter evaluation by or rule *
- * *
- * Parameters: filter - [IN] the lld filter *
- * jp_row - [IN] the lld data row *
- * lld_macro_paths - [IN] use json path to extract from jp_row *
- * info - [OUT] the warning description *
- * *
- * Return value: SUCCEED - the lld data passed filter evaluation *
- * FAIL - otherwise *
- * *
- ******************************************************************************/
-static int filter_evaluate_or(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
- const zbx_vector_ptr_t *lld_macro_paths, char **info)
-{
- int i, ret = SUCCEED;
-
- zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
-
- for (i = 0; i < filter->conditions.values_num; i++)
+ if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), &errmsgs))
{
- /* if any of conditions are true the evaluation returns true */
- if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths,
- (lld_condition_t *)filter->conditions.values[i], info)))
- {
- break;
- }
+ ret = (SUCCEED != zbx_double_compare(result, 0) ? SUCCEED : FAIL);
+ }
+ else
+ {
+ *info = zbx_strdcat(*info, error);
+ ret = FAIL;
}
+out:
+ zbx_free(expression);
+ zbx_vector_ptr_clear_ext(&errmsgs, zbx_ptr_free);
+ zbx_vector_ptr_destroy(&errmsgs);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -399,37 +396,66 @@ static int filter_evaluate_or(const lld_filter_t *filter, const struct zbx_json_
static int filter_evaluate_expression(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
const zbx_vector_ptr_t *lld_macro_paths, char **info)
{
- int i, ret = FAIL, id_len;
- char *expression, id[ZBX_MAX_UINT64_LEN + 2], *p, error[256];
- double result;
+ int i, ret = FAIL, res, error_num = 0;
+ char *expression = NULL, id[ZBX_MAX_UINT64_LEN + 2], *p, error[256], value[16],
+ *errmsg = NULL;
+ double result;
+ zbx_vector_ptr_t errmsgs;
+ size_t expression_alloc = 0, expression_offset = 0, id_len, value_len;
zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:%s", __func__, filter->expression);
- expression = zbx_strdup(NULL, filter->expression);
+ zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, filter->expression);
+
+ /* include trailing zero */
+ expression_offset++;
+
+ zbx_vector_ptr_create(&errmsgs);
for (i = 0; i < filter->conditions.values_num; i++)
{
const lld_condition_t *condition = (lld_condition_t *)filter->conditions.values[i];
- ret = filter_condition_match(jp_row, lld_macro_paths, condition, info);
+ if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths, condition, &res, &errmsg)))
+ {
+ zbx_snprintf(value, sizeof(value), "%d", res);
+ }
+ else
+ {
+ zbx_snprintf(value, sizeof(value), ZBX_UNKNOWN_STR "%d", error_num++);
+ zbx_vector_ptr_append(&errmsgs, errmsg);
+ errmsg = NULL;
+ }
zbx_snprintf(id, sizeof(id), "{" ZBX_FS_UI64 "}", condition->id);
+ value_len = strlen(value);
id_len = strlen(id);
- p = expression;
- while (NULL != (p = strstr(p, id)))
+ for (p = strstr(expression, id); NULL != p; p = strstr(p, id))
{
- *p = (SUCCEED == ret ? '1' : '0');
- memset(p + 1, ' ', id_len - 1);
- p += id_len;
+ size_t id_pos = p - expression;
+
+ zbx_replace_mem_dyn(&expression, &expression_alloc, &expression_offset, id_pos, id_len,
+ value, value_len);
+
+ p = expression + id_pos + value_len;
}
}
- if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), NULL))
+ if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), &errmsgs))
+ {
ret = (SUCCEED != zbx_double_compare(result, 0) ? SUCCEED : FAIL);
+ }
+ else
+ {
+ *info = zbx_strdcat(*info, error);
+ ret = FAIL;
+ }
zbx_free(expression);
+ zbx_vector_ptr_clear_ext(&errmsgs, zbx_ptr_free);
+ zbx_vector_ptr_destroy(&errmsgs);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -452,14 +478,15 @@ static int filter_evaluate_expression(const lld_filter_t *filter, const struct z
static int filter_evaluate(const lld_filter_t *filter, const struct zbx_json_parse *jp_row,
const zbx_vector_ptr_t *lld_macro_paths, char **info)
{
+ if (0 == filter->conditions.values_num)
+ return SUCCEED;
+
switch (filter->evaltype)
{
case CONDITION_EVAL_TYPE_AND_OR:
- return filter_evaluate_and_or(filter, jp_row, lld_macro_paths, info);
case CONDITION_EVAL_TYPE_AND:
- return filter_evaluate_and(filter, jp_row, lld_macro_paths, info);
case CONDITION_EVAL_TYPE_OR:
- return filter_evaluate_or(filter, jp_row, lld_macro_paths, info);
+ return filter_evaluate_and_or_andor(filter, jp_row, lld_macro_paths, info);
case CONDITION_EVAL_TYPE_EXPRESSION:
return filter_evaluate_expression(filter, jp_row, lld_macro_paths, info);
}