• Alexander Barkov's avatar
    MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks · 0d3720c1
    Alexander Barkov authored
    The parser works as follows:
    
    The rule expr_lex returns a pointer to a newly created sp_expr_lex
    instance which is not linked to any MariaDB structures yet - it is
    pointed only from a Bison stack variable. The sp_expr_lex instance
    gets linked to other structures (such as sp_instr_jump_if_not) later,
    after scanning some following grammar.
    
    Problem before the fix:
    If a parse error happened immediately after expr_lex (before it got linked),
    the created sp_expr_lex value got lost causing a memory leak.
    
    Fix:
    
    - Using Bison's "destructor" directive to free the results of expr_lex
      on parse/oom errors.
    
    - Moving the call for LEX::cleanup_lex_after_parse_error() from
      MYSQL_YYABORT and yyerror inside parse_sql().
      This is needed because Bison calls destructors after yyerror(),
      while it's important to delete the sp_expr_lex instance before
      LEX::cleanup_lex_after_parse_error().
      The latter frees the memory root containing the sp_expr_lex instance.
    
      After this change the code block are executed in the following order:
    
      - yyerror() -- now only raises the error to DA (no cleanup done any more)
      - %destructor { delete $$; } <expr_lex>  -- destructs the sp_expr_lex instance
      - LEX::cleanup_lex_after_parse_error()   -- frees the memory root containing
                                                  the sp_expr_lex instance
    
    - Removing the "delete sublex" related code from restore_lex():
      - restore_lex() is called in most cases on success, when delete is not needed.
      - There is one place when restore_lex() is called on error:
        In sp_create_assignment_instr(). But in this case LEX::sp_lex_in_use
        is true anyway.
        The patch adds a new DBUG_ASSERT(lex->sp_lex_in_use) to guard this.
    0d3720c1
sp_head.h 61.6 KB