1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Bug#42634: % character in query can cause mysqld signal 11 segfault

The problem is that a unfiltered user query was being passed as
the format string parameter of sql_print_warning which later
performs printf-like formatting, leading to crashes if the user
query contains formatting instructions (ie: %s). Also, it was
using THD::query as the source of the user query, but this
variable is not meaningful in some situations -- in a delayed
insert, it points to the table name.

The solution is to pass the user query as a parameter for the
format string and use the function parameter query_arg as the
source of the user query.
This commit is contained in:
Davi Arnaut
2009-02-09 16:17:58 -02:00
parent 7a6c62c4ff
commit 33a36ce9e7
3 changed files with 24 additions and 5 deletions

View File

@@ -220,3 +220,10 @@ Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format. Warning 1592 Statement is not safe to log in statement format.
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100));
INSERT INTO t1 VALUES ('a','b');
UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
DROP TABLE t1;

View File

@@ -257,3 +257,17 @@ delimiter ;|
CALL p1(); CALL p1();
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#42634: % character in query can cause mysqld signal 11 segfault
#
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100));
INSERT INTO t1 VALUES ('a','b');
UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1;
DROP TABLE t1;

View File

@@ -3660,16 +3660,14 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
if (lex->is_stmt_unsafe() && if (lex->is_stmt_unsafe() &&
variables.binlog_format == BINLOG_FORMAT_STMT) variables.binlog_format == BINLOG_FORMAT_STMT)
{ {
DBUG_ASSERT(this->query != NULL);
push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_UNSAFE_STATEMENT, ER_BINLOG_UNSAFE_STATEMENT,
ER(ER_BINLOG_UNSAFE_STATEMENT)); ER(ER_BINLOG_UNSAFE_STATEMENT));
if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
{ {
char warn_buf[MYSQL_ERRMSG_SIZE]; sql_print_warning("%s Statement: %.*s",
my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", ER(ER_BINLOG_UNSAFE_STATEMENT),
ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); MYSQL_ERRMSG_SIZE, query_arg);
sql_print_warning(warn_buf);
binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
} }
} }