← Back to team overview

maria-developers team mailing list archive

Re: [Commits] daad482: MDEV-8615: Assertion `m_cpp_buf <= begin_ptr && begin_ptr <= m_cpp_buf + m_buf_length' failed in Lex_input_stream::body_utf8_start

 

Hi, Oleksandr!

On Dec 22, Oleksandr Byelkin wrote:
> >> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> >> index a5a62ae..6611411 100644
> >> --- a/sql/sql_yacc.yy
> >> +++ b/sql/sql_yacc.yy
> >> @@ -237,6 +237,11 @@ static sp_head *make_sp_head(THD *thd, sp_name *name,
> >>   
> >>   static bool maybe_start_compound_statement(THD *thd)
> >>   {
> >> +  if (YYLIP->eof())
> >> +  {
> >> +    my_parse_error(thd, ER_SYNTAX_ERROR);
> >> +    return 1;
> >> +  }
> > no, I don't like that. Syntax errors should be issued by the parser,
> > they should follow from the grammar, not be hard-coded in some explicit
> > checks in the code.
> >
> > The problem in the current grammar - as I see it, that a code block is
> > executed before any keyword is matched. This code block assumes it's the
> > sp_unlabeled_control rule, while it could be anything.
> >
> > The fix would be to remove this code block and put this code after the
> > first keyword is matched.
> >
> >
> 
> Here is the problem. It is unlabeled context so empty label should be 
> pushed but it can not be done without that 
> maybe_start_compound_statement() if move it all inside 
> sp_control_content, then how to detect labeled or unlabeled...
> 
> So I have no any idea how it can be fixed.

Like the attached untested patch.
I simply duplicated sp_control_content rule and merged
sp_unlabeled_control into it. See how maybe_start_compound_statement()
is executed only *after* the first keyword is matched.

Of course, it's only to show the idea - the fix cannot be pushed that
way. If I were fixing it, this patch would've been the first step, and
the second step would be to merge this back into sp_control_content
removing as much of the code duplication as possible.

Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx
-- 
Vote for my Percona Live 2016 talks:
https://www.percona.com/live/data-performance-conference-2016/sessions/mariadb-connectors-fast-and-smart-new-protocol-optimizations#community-voting
https://www.percona.com/live/data-performance-conference-2016/sessions/mariadb-101-security-validation-authentication-encryption#community-voting
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a5a62ae..d54b611 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3768,20 +3768,6 @@ sp_proc_stmt_return:
           }
         ;
 
-sp_unlabeled_control:
-          {
-            if (maybe_start_compound_statement(thd))
-              MYSQL_YYABORT;
-            /* Unlabeled controls get an empty label. */
-            Lex->spcont->push_label(thd, empty_lex_str,
-                                    Lex->sphead->instructions());
-          }
-          sp_control_content
-          {
-            Lex->sphead->backpatch(Lex->spcont->pop_label());
-          }
-        ;
-
 sp_proc_stmt_leave:
           LEAVE_SYM label_ident
           {
@@ -4327,6 +4313,93 @@ sp_block_content:
           }
         ;
 
+sp_unlabeled_control:
+          LOOP_SYM
+          {
+            if (maybe_start_compound_statement(thd))
+              MYSQL_YYABORT;
+            /* Unlabeled controls get an empty label. */
+            Lex->spcont->push_label(thd, empty_lex_str,
+                                    Lex->sphead->instructions());
+          }
+          sp_proc_stmts1 END LOOP_SYM
+          {
+            LEX *lex= Lex;
+            uint ip= lex->sphead->instructions();
+            sp_label *lab= lex->spcont->last_label();  /* Jumping back */
+            sp_instr_jump *i= new (lex->thd->mem_root)
+              sp_instr_jump(ip, lex->spcont, lab->ip);
+            if (i == NULL ||
+                lex->sphead->add_instr(i))
+              MYSQL_YYABORT;
+            Lex->sphead->backpatch(Lex->spcont->pop_label());
+          }
+        | WHILE_SYM
+          {
+            if (maybe_start_compound_statement(thd))
+              MYSQL_YYABORT;
+            /* Unlabeled controls get an empty label. */
+            Lex->spcont->push_label(thd, empty_lex_str,
+                                    Lex->sphead->instructions());
+
+            Lex->sphead->reset_lex(thd); }
+          expr DO_SYM
+          {
+            LEX *lex= Lex;
+            sp_head *sp= lex->sphead;
+            uint ip= sp->instructions();
+            sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+              sp_instr_jump_if_not(ip, lex->spcont, $3, lex);
+            if (i == NULL ||
+                /* Jumping forward */
+                sp->push_backpatch(i, lex->spcont->last_label()) ||
+                sp->new_cont_backpatch(i) ||
+                sp->add_instr(i))
+              MYSQL_YYABORT;
+            if (sp->restore_lex(thd))
+              MYSQL_YYABORT;
+          }
+          sp_proc_stmts1 END WHILE_SYM
+          {
+            LEX *lex= Lex;
+            uint ip= lex->sphead->instructions();
+            sp_label *lab= lex->spcont->last_label();  /* Jumping back */
+            sp_instr_jump *i= new (lex->thd->mem_root)
+              sp_instr_jump(ip, lex->spcont, lab->ip);
+            if (i == NULL ||
+                lex->sphead->add_instr(i))
+              MYSQL_YYABORT;
+            lex->sphead->do_cont_backpatch();
+            Lex->sphead->backpatch(Lex->spcont->pop_label());
+          }
+        | REPEAT_SYM
+          {
+            if (maybe_start_compound_statement(thd))
+              MYSQL_YYABORT;
+            /* Unlabeled controls get an empty label. */
+            Lex->spcont->push_label(thd, empty_lex_str,
+                                    Lex->sphead->instructions());
+          }
+          sp_proc_stmts1 UNTIL_SYM
+          { Lex->sphead->reset_lex(thd); }
+          expr END REPEAT_SYM
+          {
+            LEX *lex= Lex;
+            uint ip= lex->sphead->instructions();
+            sp_label *lab= lex->spcont->last_label();  /* Jumping back */
+            sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+              sp_instr_jump_if_not(ip, lex->spcont, $6, lab->ip, lex);
+            if (i == NULL ||
+                lex->sphead->add_instr(i))
+              MYSQL_YYABORT;
+            if (lex->sphead->restore_lex(thd))
+              MYSQL_YYABORT;
+            /* We can shortcut the cont_backpatch here */
+            i->m_cont_dest= ip+1;
+            Lex->sphead->backpatch(Lex->spcont->pop_label());
+          }
+        ;
+
 sp_control_content:
           LOOP_SYM
           sp_proc_stmts1 END LOOP_SYM

References