mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger
The problem resided in this branch of the "option_value_no_option_type" rule: | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default Summary: 1. internal_variable_name initialized tmp.var to trg_new_row_fake_var (0x01). 2. The condition "if (tmp.var == NULL)" did not check the special case with trg_new_row_fake_var, so Lex->set_system_variable(&tmp, $3, $6) was called with tmp.var pointing to trg_new_row_fake_var, which created a sys_var instance pointing to 0x01 instead of a real system variable. 3. Later, at the trigger invocation time, this method was called: sys_var::do_deprecated_warning (this=0x1, thd=0x7ffe6c000a98) Notice, "this" is equal to trg_new_row_fake_var (0x01) Solution: The old implementation with separate rules internal_variable_name (in sql_yacc.yy and sql_yacc_ora.yy) and internal_variable_name_directly_assignable (in sql_yacc_ora.yy only) was too complex and hard to follow. Rewriting the code in a more straightforward way. 1. Changing LEX::set_system_variable() from: bool set_system_variable(struct sys_var_with_base *, enum_var_type, Item *); to: bool set_system_variable(enum_var_type, sys_var *, const LEX_CSTRING *, Item *); 2. Adding new methods in LEX, which operate with variable names: bool set_trigger_field(const LEX_CSTRING *, const LEX_CSTRING *, Item *); bool set_system_variable(enum_var_type var_type, const LEX_CSTRING *name, Item *val); bool set_system_variable(THD *thd, enum_var_type var_type, const LEX_CSTRING *name1, const LEX_CSTRING *name2, Item *val); bool set_default_system_variable(enum_var_type var_type, const LEX_CSTRING *name, Item *val); bool set_variable(const LEX_CSTRING *name, Item *item); 3. Changing the grammar to call the new methods directly in option_value_no_option_type, Removing rules internal_variable_name and internal_variable_name_directly_assignable. 4. Removing "struct sys_var_with_base" and trg_new_row_fake_var. Good side effect: - The code in /sql reduced from 314 to 183 lines. - MDEV-15615 Unexpected syntax error instead of "Unknown system variable" ... was also fixed automatically
This commit is contained in:
@ -155,15 +155,6 @@ extern uint binlog_unsafe_map[256];
|
||||
void binlog_unsafe_map_init();
|
||||
#endif
|
||||
|
||||
/**
|
||||
used by the parser to store internal variable name
|
||||
*/
|
||||
struct sys_var_with_base
|
||||
{
|
||||
sys_var *var;
|
||||
LEX_CSTRING base_name;
|
||||
};
|
||||
|
||||
struct LEX_TYPE
|
||||
{
|
||||
enum enum_field_types type;
|
||||
@ -1338,8 +1329,6 @@ struct st_trg_chistics: public st_trg_execution_order
|
||||
|
||||
};
|
||||
|
||||
extern sys_var *trg_new_row_fake_var;
|
||||
|
||||
enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
|
||||
XA_SUSPEND, XA_FOR_MIGRATE};
|
||||
|
||||
@ -3220,9 +3209,20 @@ public:
|
||||
enum sub_select_type type,
|
||||
bool is_top_level);
|
||||
bool setup_select_in_parentheses();
|
||||
bool set_trigger_new_row(LEX_CSTRING *name, Item *val);
|
||||
bool set_system_variable(struct sys_var_with_base *tmp,
|
||||
enum enum_var_type var_type, Item *val);
|
||||
bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
|
||||
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
|
||||
Item *val);
|
||||
bool set_system_variable(enum_var_type var_type, sys_var *var,
|
||||
const LEX_CSTRING *base_name, Item *val);
|
||||
bool set_system_variable(enum_var_type var_type, const LEX_CSTRING *name,
|
||||
Item *val);
|
||||
bool set_system_variable(THD *thd, enum_var_type var_type,
|
||||
const LEX_CSTRING *name1,
|
||||
const LEX_CSTRING *name2,
|
||||
Item *val);
|
||||
bool set_default_system_variable(enum_var_type var_type,
|
||||
const LEX_CSTRING *name,
|
||||
Item *val);
|
||||
bool set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val);
|
||||
void set_stmt_init();
|
||||
sp_name *make_sp_name(THD *thd, const LEX_CSTRING *name);
|
||||
@ -3265,14 +3265,7 @@ public:
|
||||
sp_pcontext *not_used_ctx;
|
||||
return find_variable(name, ¬_used_ctx, rh);
|
||||
}
|
||||
bool init_internal_variable(struct sys_var_with_base *variable,
|
||||
const LEX_CSTRING *name);
|
||||
bool init_internal_variable(struct sys_var_with_base *variable,
|
||||
const LEX_CSTRING *dbname,
|
||||
const LEX_CSTRING *name);
|
||||
bool init_default_internal_variable(struct sys_var_with_base *variable,
|
||||
LEX_CSTRING name);
|
||||
bool set_variable(struct sys_var_with_base *variable, Item *item);
|
||||
bool set_variable(const LEX_CSTRING *name, Item *item);
|
||||
bool set_variable(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
|
||||
Item *item);
|
||||
void sp_variable_declarations_init(THD *thd, int nvars);
|
||||
@ -3464,7 +3457,7 @@ public:
|
||||
const LEX_CSTRING *var_name,
|
||||
const LEX_CSTRING *field_name);
|
||||
|
||||
bool is_trigger_new_or_old_reference(const LEX_CSTRING *name);
|
||||
bool is_trigger_new_or_old_reference(const LEX_CSTRING *name) const;
|
||||
|
||||
Item *create_and_link_Item_trigger_field(THD *thd, const LEX_CSTRING *name,
|
||||
bool new_row);
|
||||
|
Reference in New Issue
Block a user