Skip to content

Commit

Permalink
..F.....S. [ZBX-21898] added escaping of backslashes in history funct…
Browse files Browse the repository at this point in the history
…ion string parameters

* commit 'e85104ef361ebfff38809a17d093144bf5593ac4':
  ........S. [ZBX-21898] fixed jenkins warning
  ..F....... [ZBX-21898] updated phpdoc for expression parser and history function parser
  ..F....... [ZBX-21898] added some code refactoring
  ..F....... [ZBX-21898] added import converter for simple triggers and maps, added expression parser for all history functionst, fixed coding style
  .......... [ZBX-21898] added changelog and code style fixes
  ..F....... [ZBX-21898] reworked import converted to pass flag to CHistFunctionParser instead of creating new class alias
  ..F....... [ZBX-21898] renamed C10HistFunctionParser to C54HistFunctionParser
  ..F....... [ZBX-21898] added import converter from 6.4 to 7.0 to convert expressions to new format
  ........S. [ZBX-21898] fixed db patch for trigger expressions
  ........S. [ZBX-21898] adjusted DB patch to work on master
  ........S. [ZBX-21898] reverted changes made during changes that were wrongully commited
  ........S. [ZBX-21898] added dbpatch for fixed trigger expression syntax for history functions
  ........S. [ZBX-21898] added backslash escaping to the server in trigger and calculated item expressions, no change for key escaping
  • Loading branch information
Konstantins Prutkovs committed Jul 3, 2023
2 parents bf403ef + e85104e commit f011431
Show file tree
Hide file tree
Showing 14 changed files with 613 additions and 48 deletions.
1 change: 1 addition & 0 deletions ChangeLog.d/bugfix/ZBX-21898
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
..F.....S. [ZBX-21898] added escaping of backslashes in history function string parameters (epulke, kprutkovs)
2 changes: 1 addition & 1 deletion create/src/schema.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2120,4 +2120,4 @@ TABLE|dbversion|dbversionid|
FIELD |dbversionid |t_id | |NOT NULL |0
FIELD |mandatory |t_integer |'0' |NOT NULL |
FIELD |optional |t_integer |'0' |NOT NULL |
ROW |1 |6050025 |6050025
ROW |1 |6050027 |6050027
3 changes: 3 additions & 0 deletions include/zbxeval.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ typedef int (*zbx_macro_expand_func_t)(void *data, char **str, const zbx_uint64_
char **error);

int zbx_eval_parse_expression(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules, char **error);
int zbx_eval_parse_expression_str_v64_compat(zbx_eval_context_t *ctx, const char *expression,
zbx_uint64_t rules, char **error);
void zbx_eval_init(zbx_eval_context_t *ctx);
void zbx_eval_clear(zbx_eval_context_t *ctx);
int zbx_eval_status(const zbx_eval_context_t *ctx);
Expand Down Expand Up @@ -253,6 +255,7 @@ char *zbx_eval_format_function_error(const char *function, const char *host, con
const char *parameter, const char *error);

void zbx_eval_extract_item_refs(zbx_eval_context_t *ctx, zbx_vector_str_t *refs);
int zbx_eval_compare_tokens_by_loc(const void *d1, const void *d2);

typedef struct
{
Expand Down
2 changes: 2 additions & 0 deletions include/zbxexpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ int zbx_function_find(const char *expr, size_t *func_pos, size_t *par_l, size_t
void zbx_function_param_parse(const char *expr, size_t *param_pos, size_t *length, size_t *sep_pos);
char *zbx_function_param_unquote_dyn(const char *param, size_t len, int *quoted);
int zbx_function_param_quote(char **param, int forced);
char *zbx_function_param_unescape_dyn(const char *param, size_t len, int *quoted);
int zbx_function_param_escape(char **param, int forced);
char *zbx_function_get_param_dyn(const char *params, int Nparam);

typedef enum
Expand Down
6 changes: 3 additions & 3 deletions src/libs/zbxcacheconfig/dbconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -14879,15 +14879,15 @@ char *zbx_dc_expand_user_macros_in_func_params(const char *params, zbx_uint64_t
for (ptr = params; ptr < params + params_len; ptr += sep_pos + 1)
{
size_t param_pos, param_len;
int quoted;
int escaped;
char *param;

zbx_function_param_parse(ptr, &param_pos, &param_len, &sep_pos);

param = zbx_function_param_unquote_dyn(ptr + param_pos, param_len, &quoted);
param = zbx_function_param_unescape_dyn(ptr + param_pos, param_len, &escaped);
(void)zbx_dc_expand_user_macros(um_handle, &param, &hostid, 1, NULL);

if (SUCCEED == zbx_function_param_quote(&param, quoted))
if (SUCCEED == zbx_function_param_escape(&param, escaped))
zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, param);
else
zbx_strncpy_alloc(&buf, &buf_alloc, &buf_offset, ptr + param_pos, param_len);
Expand Down
197 changes: 197 additions & 0 deletions src/libs/zbxdbupgrade/dbupgrade_6050.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include "dbupgrade.h"

#include "zbxdbschema.h"
#include "zbxexpr.h"
#include "zbxeval.h"
#include "zbxalgo.h"
#include "zbxdbhigh.h"

/*
Expand Down Expand Up @@ -297,6 +300,198 @@ static int DBpatch_6050025(void)
return SUCCEED;
}

static char *fix_hist_param_escaping(const char *param, size_t left, size_t right)
{
size_t escaped_len = 0;
/* resulting string cannot be more than 2 times longer than original string */
char *escaped = zbx_malloc(NULL, 2 * (right - left + 1) * sizeof(char) + 1);

for (size_t i = left; i <= right; i++)
{
escaped[escaped_len++] = param[i];
if (i < right && '\\' == param[i] && '"' != param[i + 1])
escaped[escaped_len++] = '\\';
}
escaped[escaped_len++] = '\0';

return escaped;
}

static int DBpatch_6050026(void)
{
zbx_db_result_t result;
zbx_db_row_t row;
int ret = SUCCEED;
char *sql = NULL;
size_t sql_alloc = 0, sql_offset = 0;

zbx_db_begin_multiple_update(&sql, &sql_alloc, &sql_offset);

/* functions table contains history functions used in trigger expressions */
result = zbx_db_select("select functionid,parameter from functions where length(parameter) > 1");

while (SUCCEED == ret && NULL != (row = zbx_db_fetch(result)))
{
const char *ptr;
char *buf, *tmp, *param = NULL;
size_t param_pos, param_len, sep_pos, buf_alloc, buf_offset = 0;

buf_alloc = strlen(row[1]);
buf = zbx_malloc(NULL, buf_alloc);

for (ptr = row[1]; ptr < row[1] + strlen(row[1]); ptr += sep_pos + 1)
{
zbx_function_param_parse(ptr, &param_pos, &param_len, &sep_pos);

if (param_pos < sep_pos)
{
param = fix_hist_param_escaping(ptr, param_pos, sep_pos - 1);
zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, param);
}

if (',' == ptr[sep_pos])
zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, ',');
zbx_free(param);
}

tmp = zbx_db_dyn_escape_string(buf);
zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
"update functions set parameter='%s' where functionid=%s;\n", tmp, row[0]);
zbx_free(tmp);
zbx_free(buf);

if (SUCCEED == ret)
ret = zbx_db_execute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
}

zbx_db_free_result(result);
zbx_db_end_multiple_update(&sql, &sql_alloc, &sql_offset);

if (SUCCEED == ret && 16 < sql_offset)
{
if (ZBX_DB_OK > zbx_db_execute("%s", sql))
ret = FAIL;
}

zbx_free(sql);

return ret;
}

typedef struct {
zbx_uint32_t op_num;
char is_hist;
} expr_fun_call;

ZBX_VECTOR_DECL(fun_stack, expr_fun_call)
ZBX_VECTOR_IMPL(fun_stack, expr_fun_call)

static int DBpatch_6050027(void)
{
int ret = SUCCEED;
zbx_eval_context_t ctx;
int token_num;
const zbx_eval_token_t *token;
zbx_vector_fun_stack_t fun_stack;
zbx_vector_ptr_t hist_param_tokens;
zbx_db_result_t result;
zbx_db_row_t row;
char *tmp, *substitute = NULL, *sql = NULL, *error = NULL;
size_t sql_alloc = 0, sql_offset = 0;

zbx_vector_fun_stack_create(&fun_stack);
zbx_vector_ptr_create(&hist_param_tokens);

zbx_db_begin_multiple_update(&sql, &sql_alloc, &sql_offset);

if (NULL == (result = zbx_db_select("select itemid,params from items where type = 15")))
goto clean;

while (NULL != (row = zbx_db_fetch(result)))
{
ret = zbx_eval_parse_expression_str_v64_compat(&ctx, row[1], ZBX_EVAL_PARSE_CALC_EXPRESSION, &error);
if (FAIL == ret)
{
zabbix_log(LOG_LEVEL_CRIT, "Failed to parse calculated item expression \"%s\" for"
" item with id %s, error: %s", row[1], row[0], error);
goto clean;
}
zbx_free(error);

zbx_vector_fun_stack_clear(&fun_stack);
zbx_vector_ptr_clear(&hist_param_tokens);
substitute = zbx_strdup(NULL, ctx.expression);

/* finding string parameters of history functions */
for (token_num = ctx.stack.values_num - 1; token_num >= 0; token_num--)
{
token = &ctx.stack.values[token_num];

if (0 < fun_stack.values_num) {
expr_fun_call *cur_call = &(fun_stack.values[fun_stack.values_num - 1]);

if (ZBX_EVAL_TOKEN_VAR_STR == token->type && cur_call->is_hist)
zbx_vector_ptr_append(&hist_param_tokens, (void *)token);

if (0 == --(cur_call->op_num))
fun_stack.values_num--;
}

if (0 < token->opt)
{
expr_fun_call call = {token->opt, ZBX_EVAL_TOKEN_HIST_FUNCTION == token->type};

zbx_vector_fun_stack_append(&fun_stack, call);
}
}

/* Substitution logic relies on replacing further-most tokens first */
zbx_vector_ptr_sort(&hist_param_tokens, zbx_eval_compare_tokens_by_loc);

/* adding necessary escaping to the the string parameters of history functions */
for (token_num = 0; token_num < hist_param_tokens.values_num; token_num++)
{
size_t right_pos;

token = hist_param_tokens.values[token_num];
right_pos = token->loc.r;
tmp = fix_hist_param_escaping(substitute, token->loc.l, right_pos);
zbx_replace_string(&substitute, token->loc.l, &right_pos, tmp);

zbx_free(tmp);
}

tmp = zbx_db_dyn_escape_string(substitute);
zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update items set params='%s' where itemid=%s;\n",
tmp, row[0]);
zbx_free(tmp);
zbx_free(substitute);
zbx_eval_clear(&ctx);

if (SUCCEED == ret)
ret = zbx_db_execute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
}

zbx_db_free_result(result);
zbx_db_end_multiple_update(&sql, &sql_alloc, &sql_offset);

if (SUCCEED == ret && 16 < sql_offset)
{
if (ZBX_DB_OK > zbx_db_execute("%s", sql))
ret = FAIL;
}

clean:
zbx_free(error);
zbx_free(substitute);

zbx_vector_fun_stack_destroy(&fun_stack);
zbx_vector_ptr_destroy(&hist_param_tokens);
zbx_free(sql);

return ret;
}

#endif

DBPATCH_START(6050)
Expand Down Expand Up @@ -329,5 +524,7 @@ DBPATCH_ADD(6050022, 0, 1)
DBPATCH_ADD(6050023, 0, 1)
DBPATCH_ADD(6050024, 0, 1)
DBPATCH_ADD(6050025, 0, 1)
DBPATCH_ADD(6050026, 0, 1)
DBPATCH_ADD(6050027, 0, 1)

DBPATCH_END()
6 changes: 3 additions & 3 deletions src/libs/zbxeval/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void zbx_eval_deserialize(zbx_eval_context_t *ctx, const char *expression, zbx_u
}
}

static int compare_tokens_by_loc(const void *d1, const void *d2)
int zbx_eval_compare_tokens_by_loc(const void *d1, const void *d2)
{
const zbx_eval_token_t *t1 = *(const zbx_eval_token_t * const *)d1;
const zbx_eval_token_t *t2 = *(const zbx_eval_token_t * const *)d2;
Expand Down Expand Up @@ -370,7 +370,7 @@ void zbx_eval_compose_expression(const zbx_eval_context_t *ctx, char **expressio
zbx_vector_ptr_append(&tokens, &ctx->stack.values[i]);
}

zbx_vector_ptr_sort(&tokens, compare_tokens_by_loc);
zbx_vector_ptr_sort(&tokens, zbx_eval_compare_tokens_by_loc);

for (i = 0; i < tokens.values_num; i++)
{
Expand Down Expand Up @@ -786,7 +786,7 @@ void zbx_eval_get_functionids_ordered(zbx_eval_context_t *ctx, zbx_vector_uint64
zbx_vector_ptr_append(&tokens, &ctx->stack.values[i]);
}

zbx_vector_ptr_sort(&tokens, compare_tokens_by_loc);
zbx_vector_ptr_sort(&tokens, zbx_eval_compare_tokens_by_loc);

for (i = 0; i < tokens.values_num; i++)
{
Expand Down
Loading

0 comments on commit f011431

Please sign in to comment.