/
niceSOFT
/
util-linux
Обзор
Документация
Войти
/
niceSOFT
/
util-linux
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
libsmartcols/src/filter-parser.y
249 строк
5 KB
Karel Zak
libsmartcols: harden filter parser against fuzzer issues
24 июн 2026, 12:20
24 июн 2026, 12:20
d7ed845
Код
Авторство
О чём код?
%{ /* * Compilers detect yynerrs as unused. Let's hope it will be fixed in future * versions of Bison. */ #if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic ignored "-Wunused-but-set-variable" #elif defined(__clang__) # pragma clang diagnostic ignored "-Wunused-but-set-variable" #endif #include <stdio.h> #include "smartcolsP.h" #include "filter-parser.h" #include "filter-scanner.h" void yyerror(yyscan_t *locp, struct libscols_filter *fltr, char const *fmt, ...); #define YYMAXDEPTH 256 %} %define api.pure full %lex-param {void *scanner} %parse-param {void *scanner}{struct libscols_filter *fltr} %define parse.error verbose %code requires { } /* Elegant way, but not compatible with biron -y (autotools): %define api.value.type union %token <unsigned long long> param_number %token <const char*> param_string %token <const char*> param_name %token <long double> param_float %type <struct filter_node*> param %type <struct filter_node*> expr */ %union { unsigned long long param_number; const char* param_string; const char* param_name; long double param_float; struct filter_node *param; struct filter_node *expr; } %token <param_number> T_NUMBER %token <param_string> T_STRING %token <param_name> T_HOLDER %token <param_float> T_FLOAT %type <param> param expr %token T_OR T_AND T_EQ T_NE T_LT T_LE T_GT T_GE T_REG T_NREG T_TRUE T_FALSE T_NEG %left T_OR T_AND %left T_EQ T_NE T_LT T_LE T_GT T_GE T_REG T_NREG T_TRUE T_FALSE T_NEG %token T_INVALID_NUMBER %destructor { /* This destruct is called on error. The root node will be deallocated * by scols_unref_filter(). */ if (fltr->root != $$) filter_unref_node($$); } <param> %% %start filter; filter: expr { fltr->root = $1; } ; expr: param { $$ = $1; } | '(' expr ')' { $$ = $2; } | expr T_AND expr { $$ = filter_new_expr(fltr, F_EXPR_AND, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_OR expr { $$ = filter_new_expr(fltr, F_EXPR_OR, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | T_NEG expr { $$ = filter_new_expr(fltr, F_EXPR_NEG, NULL, $2); if (!$$) { filter_unref_node($2); YYERROR; } } | expr T_EQ expr { $$ = filter_new_expr(fltr, F_EXPR_EQ, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_NE expr { $$ = filter_new_expr(fltr, F_EXPR_NE, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_LE expr { $$ = filter_new_expr(fltr, F_EXPR_LE, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_LT expr { $$ = filter_new_expr(fltr, F_EXPR_LT, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_GE expr { $$ = filter_new_expr(fltr, F_EXPR_GE, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_GT expr { $$ = filter_new_expr(fltr, F_EXPR_GT, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_REG expr { $$ = NULL; if (filter_compile_param(fltr, (struct filter_param *) $3) == 0) $$ = filter_new_expr(fltr, F_EXPR_REG, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } | expr T_NREG expr { $$ = NULL; if (filter_compile_param(fltr, (struct filter_param *) $3) == 0) $$ = filter_new_expr(fltr, F_EXPR_NREG, $1, $3); if (!$$) { filter_unref_node($1); filter_unref_node($3); YYERROR; } } ; param: T_NUMBER { $$ = filter_new_param(fltr, SCOLS_DATA_U64, 0, (void *) (&$1)); if (!$$) YYERROR; } | T_FLOAT { $$ = filter_new_param(fltr, SCOLS_DATA_FLOAT, 0, (void *) (&$1)); if (!$$) YYERROR; } | T_HOLDER { $$ = filter_new_param(fltr, SCOLS_DATA_NONE, F_HOLDER_COLUMN, (void *) $1); if (!$$) YYERROR; } | T_STRING { $$ = filter_new_param(fltr, SCOLS_DATA_STRING, 0, (void *) $1); if (!$$) YYERROR; } | T_TRUE { bool x = true; $$ = filter_new_param(fltr, SCOLS_DATA_BOOLEAN, 0, (void *) &x); if (!$$) YYERROR; } | T_FALSE { bool x = false; $$ = filter_new_param(fltr, SCOLS_DATA_BOOLEAN, 0, (void *) &x); if (!$$) YYERROR; } | T_INVALID_NUMBER { /* YYerror token is unsupported in old Bisons */ ignore_result( $$ ); /* suppress "unset value" warning */ YYERROR; /* yyerror() already called by lex() */ } ; %% void yyerror (yyscan_t *locp __attribute__((__unused__)), struct libscols_filter *fltr, char const *fmt, ...) { if (fmt && fltr) { char *p; va_list ap; int e; if (fltr->errmsg) { free(fltr->errmsg); fltr->errmsg = NULL; } va_start(ap, fmt); e = vasprintf(&fltr->errmsg, fmt, ap); va_end(ap); if (e < 0 || !fltr->errmsg) return; p = strstr(fltr->errmsg, "T_"); if (p) { size_t sz = strlen(fltr->errmsg); memmove(p, p + 2, sz - 1 - (p - fltr->errmsg)); } } errno = EINVAL; }