Browse Source

MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash

The bug was introduced in the patch for "MDEV-10597 Cursors with parameters".
The LEX created in assignment_source_expr was not put into
thd->lex->sphead->m_lex (the stack of LEX'es), so syntax error in "expr"
caused a wrong memory cleanup in sp_head::~sp_head().

The fix changes the code to use sp_head::push_lex() followed by
sp_head::restore_lex(), like it happens in all other similar cases.
pull/381/head
Alexander Barkov 9 years ago
parent
commit
400de20279
  1. 26
      mysql-test/suite/compat/oracle/r/sp-cursor.result
  2. 23
      mysql-test/suite/compat/oracle/t/sp-cursor.test
  3. 17
      sql/sp_head.cc
  4. 3
      sql/sp_head.h
  5. 15
      sql/sql_yacc_ora.yy

26
mysql-test/suite/compat/oracle/r/sp-cursor.result

@ -753,6 +753,32 @@ DROP PROCEDURE p1;
# End of MDEV-10597 Cursors with parameters
#
#
# MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
#
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (1,'A');
CREATE PROCEDURE p1(a INT,b VARCHAR)
AS
CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
BEGIN
OPEN c(a+, b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE c;
END;
$$
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE ' at line 5
DROP TABLE t1;
#
# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
#
CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));

23
mysql-test/suite/compat/oracle/t/sp-cursor.test

@ -751,6 +751,29 @@ DROP PROCEDURE p1;
--echo # End of MDEV-10597 Cursors with parameters
--echo #
--echo #
--echo # MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
--echo #
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (1,'A');
DELIMITER $$;
--error ER_PARSE_ERROR
CREATE PROCEDURE p1(a INT,b VARCHAR)
AS
CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
BEGIN
OPEN c(a+, b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE c;
END;
$$
DELIMITER ;$$
DROP TABLE t1;
--echo #
--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations

17
sql/sp_head.cc

@ -2144,20 +2144,23 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
*/
bool
sp_head::reset_lex(THD *thd)
sp_head::reset_lex(THD *thd, sp_lex_local *sublex)
{
DBUG_ENTER("sp_head::reset_lex");
LEX *oldlex= thd->lex;
sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, oldlex);
if (sublex == 0)
DBUG_RETURN(TRUE);
thd->set_local_lex(sublex);
(void)m_lex.push_front(oldlex);
DBUG_RETURN(m_lex.push_front(oldlex));
}
DBUG_RETURN(FALSE);
bool
sp_head::reset_lex(THD *thd)
{
DBUG_ENTER("sp_head::reset_lex");
sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, thd->lex);
DBUG_RETURN(sublex ? reset_lex(thd, sublex) : true);
}

3
sql/sp_head.h

@ -474,6 +474,9 @@ public:
bool
reset_lex(THD *thd);
bool
reset_lex(THD *thd, sp_lex_local *sublex);
/**
Merge two LEX instances.
@param oldlex - the upper level LEX we're going to restore to.

15
sql/sql_yacc_ora.yy

@ -3290,19 +3290,20 @@ assignment_source_lex:
;
assignment_source_expr:
remember_lex assignment_source_lex
assignment_source_lex
{
DBUG_ASSERT(thd->free_list == NULL);
thd->set_local_lex($2); // This changes thd->lex to $2
Lex->sphead->reset_lex(thd, $1);
}
expr
{
DBUG_ASSERT($2 == thd->lex);
if (thd->restore_from_local_lex_to_old_lex($1)) // Restores thd->lex
MYSQL_YYABORT;
$$= $2;
$$->set_item_and_free_list($4, thd->free_list);
DBUG_ASSERT($1 == thd->lex);
$$= $1;
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;

Loading…
Cancel
Save