ITEM_PARAM::SAFE_CHARSET_CONVERTER
ISSUE:
------
Charset conversion on a null parameter is not handled
correctly.
SOLUTION:
---------
Item_param's charset converter does not handle the case
where it might have to deal with a null value. This is
fine for other charset converters since the value is not
supplied to them at runtime.
The fix is to check if the parameter is now set to null and
return an Item_null object. Also, there is no need to
initialize Item_param's cnvitem in the constructor to a
string. This can be done in
ITEM_PARAM::SAFE_CHARSET_CONVERTER itself.
Members of Item_param, cnvbuf and cnvstr, have been removed
and cnvitem has been made a local variable in
ITEM_PARAM::SAFE_CHARSET_CONVERTER.
'SYSTEM LOCK' IN PROCESSLIST
Analysis
=========
Show processlist shows 'System Lock' in 'State' field while
LOAD DATA INFILE is running.
thd->proc_info update is missing in LOAD DATA INFILE path.
Thus any request will get last unpdated status from lock_table()
during open_table().
Fix:
=======
Update state information from LOAD DATA INFILE path.
GENERATED BY THE EXP() FUNCTION
When generating the error message for numeric overflow, pass a flag to
Item::print() that prevents it from expanding constant expressions and
parameters to the values they evaluate to.
For consistency, also pass the flag to Item::print() when
Item_func_spatial_collection::fix_length_and_dec() generates an error
message. It doesn't make any difference at the moment, since constant
expressions haven't been evaluated yet when this function is called.
PROCEDURE RESULTS IN GARBAGE BYTES
Issue:
-----
This problem occurs under the following conditions:
a) Stored procedure has a variable is declared as TEXT/BLOB.
b) Data is copied into the the variable using the
SELECT...INTO syntax from a TEXT/BLOB column.
Data corruption can occur in such cases.
SOLUTION:
---------
The blob type does not allocate space for the string to be
stored. Instead it contains a pointer to the source string.
Since the source is deallocated immediately after the
select statement, this can cause data corruption.
As part of the fix for Bug #21143080, when the source was
part of the table's write-set, blob would allocate the
neccessary space. But this fix missed the possibility that,
as in the above case, the target might be a variable.
The fix will add the copy_blobs check that was removed by
the earlier fix.
UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M"
Issue:
-----
When an invalid date is supplied to the UNIX_TIMESTAMP
function from STR_TO_DATE, no check is performed before
converting it to a timestamp value.
SOLUTION:
---------
Add the check_date function and only if it succeeds,
proceed to the timestamp conversion.
No warning will be returned for dates having zero in
month/date, since partial dates are allowed. UNIX_TIMESTAMP
will return only a zero for such values.
The problem has been handled in 5.6+ with WL#946.
COLUMNS
ANALYSIS:
=========
A valgrind error is reported when CREATE TABLE .. SELECT
involving BIT columns triggers a column type redefinition.
In general the pack_flag is set for BIT columns in
'mysql_prepare_create_table()'. However, during the above
operation, redefined column types was handled after the
special handling for BIT columns and thus pack_flag ended
up not being set correctly triggering the valgrind error.
FIX:
====
The patch fixes this problem by setting pack_flag correctly
for BIT columns in the case of column type redefinition.
Problem:
=======
rpl_binlog_index.test fails with following valgrind error.
line
Conditional jump or move depends on uninitialised value(s)
at 0x4C2F842: __memcmp_sse4_1 (in /usr/lib64/valgrind/
vgpreload_memcheck-amd64-linux.so)
0x739E39: find_uniq_filename(char*) (log.cc:2212)
0x73A11B: MYSQL_LOG::generate_new_name(char*, char const*)
(log.cc:2492)
0x73A1ED: MYSQL_LOG::init_and_set_log_file_name(char const*,
char const*, enum_log_type, cache_type) (log.cc:2289)
0x73B6F5: MYSQL_BIN_LOG::open(char const*, enum_log_type,
Analysis and fix:
=================
This issue was fixed as part of Bug#20459363 fix in 5.6 and
above. Hence backporting the fix to MySQL-5.5.
that was mistakenly merged from mysql-5.5.47
(introduces valgrind failures in main.sp, because Field_varstring
columns are created as FIELD_NORMAL and that causes aria to
read bytes between the actual value length and field max length)
Item_func_coalesce::fix_length_and_dec() calls
Item_func::count_string_result_length()) which called agg_arg_charsets()
with wrong flags, so the collation derivation of the COALESCE result was
not properly set to DERIVATION_COERCIBLE. It erroneously stayed
DERIVATION_NUMERIC. So GREATEST() misinterpreted the argument as
a number rather that a string and did not calculate its own length properly.
Problem:
========
1) Drop table queries are re-generated by server
before writing the events(queries) into binlog
for various reasons. If table name/db name contains
a non regular characters (like latin characters),
the generated query is wrong. Hence it breaks the
replication.
2) In the edge case, when table name/db name contains
64 characters, server is throwing an assert
assert(M_TBLLEN < 128)
3) In the edge case, when db name contains 64 latin
characters, binlog content is interpreted badly
which is leading replication failure.
Analysis & Fix :
================
1) Parser reads the table name from the query and converts
it to standard charset(utf8) and stores it in table_name variable.
When drop table query is regenerated with the same table_name
variable, it should be converted back to the original charset
from standard charset(utf8).
2) Latin character takes two bytes for each character. Limit
of the identifier is 64. SYSTEM_CHARSET_MBMAXLEN is set to '3'.
So there is a possiblity that tablename/dbname contains 3 * 64.
Hence assert is changed to
(M_TBLLEN <= NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN)
3) db_len in the binlog event header is taking 1 byte.
db_len is ranged from 0 to 192 bytes (3 * 64).
While reading the db_len from the event, server
is casting to uint instead of uchar which is leading
to bad db_len. This problem is fixed by changing the
cast type to uchar.
Problem:
At the end of first execution select_lex->prep_where is pointing to
a runtime created object (temporary table field). As a result
server exits trying to access a invalid pointer during second
execution.
Analysis:
While optimizing the join conditions for the query, after the
permanent transformation, optimizer makes a copy of the new
where conditions in select_lex->prep_where. "prep_where" is what
is used as the "where condition" for the query at the start of execution.
W.r.t the query in question, "where" condition is actually pointing
to a field in the temporary table. As a result, for the second
execution the pointer is no more valid resulting in server exit.
Fix:
At the end of the first execution, select_lex->where will have the
original item of the where condition.
Make prep_where the new place where the original item of select->where
has to be rolled back.
Fixed in 5.7 with the wl#7082 - Move permanent transformations from
JOIN::optimize to JOIN::prepare
Patch for 5.5 includes the following backports from 5.6:
Bugfix for Bug12603141 - This makes the first execute statement in the testcase
pass in 5.5
However it was noted later in in Bug16163596 that the above bugfix needed to
be modified. Although Bug16163596 is reproducible only with changes done for
Bug12582849, we have decided include the fix.
Considering that Bug12582849 is related to Bug12603141, the fix is
also included here. However this results in Bug16317817, Bug16317685,
Bug16739050. So fix for the above three bugs is also part of this patch.
Problem & Analysis: If DML invokes a trigger or a
stored function that inserts into an AUTO_INCREMENT column,
that DML has to be marked as 'unsafe' statement. If the
tables are locked in the transaction prior to DML statement
(using LOCK TABLES), then the same statement is not marked as
'unsafe' statement. The logic of checking whether unsafeness
is protected with if (!thd->locked_tables_mode). Hence if
we lock the tables prior to DML statement, it is *not* entering
into this if condition. Hence the statement is not marked
as unsafe statement.
Fix: Irrespective of locked_tables_mode value, the unsafeness
check should be done. Now with this patch, the code is moved
out to 'decide_logging_format()' function where all these checks
are happening and also with out 'if(!thd->locked_tables_mode)'.
Along with the specified test case in the bug scenario
(BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS), we also identified that
other cases BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST,
BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT, BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS
are also protected with thd->locked_tables_mode which is not right. All
of those checks also moved to 'decide_logging_format()' function.
HA_MYISAMMRG.CC:631
Analysis
========
Any attempt to open a temporary MyISAM merge table consisting
of a view in its list of tables (not the last table in the list)
under LOCK TABLES causes the server to exit.
Current implementation doesn't perform sanity checks during
merge table creation. This allows merge table to be created
with incompatible tables (table with non-myisam engine),
views or even with table doesn't exist in the system.
During view open, check to verify whether requested view
is part of a merge table is missing under LOCK TABLES path
in open_table(). This leads to opening of underlying table
with parent_l having NULL value. Later when attaching child
tables to parent, this hits an ASSERT as all child tables
should have parent_l pointing to merge parent. If the operation
does not happen under LOCK TABLES mode, open_table() checks
for view's parent_l and returns error.
Fix:
======
Check added before opening view Under LOCK TABLES in open_table()
to verify whether it is part of merge table. Error is returned
if the view is part of a merge table.
DOING BAD DDL IN PREPARED STATEMENT
Analysis
========
A repeat execution of the prepared statement 'ALTER TABLE v1
CHECK PARTITION' where v1 is a view leads to server exit.
ALTER TABLE ... CHECK PARTITION is not applicable for views
and check for the same check is missing. This leads to
further execution and creation of derived table for the view
(Allocated under temp_table mem_root). Any reference to open
view or related pointers from second execution leads to
server exit as the same was freed at previous execution closure.
Fix:
======
Added check for view in mysql_admin_table() on PARTITION
operation. This will prevent mysql_admin_table() from
going ahead and creating temp table and related issues.
Changed message on admin table view operation error to
be more appropriate.
MDEV-8938 Server Crash on Update with joins
Make unique table check after setup_fields of update because unique table can materialize table and we do not need field resolving after materialization.
Issue:
-----
When a varchar column is used to fill the record in an
internal temporary table, the length of the string stored
in the column is not taken into account. Instead the
default length of packed data is used to copy with memmove.
This will cause valgrind issues since some bytes are
uninitialized.
SOLUTION:
---------
The solution is to take into account the length of the
string stored in the column while filling the record.
This fix is a backport of BUG#13389854.
Issue
-----
This problem occurs when varchar columns are used in a
internal temporary table. The type of the field is set
incorrectly to the generic FIELD_NORMAL type. This in turn
results in an inaccurate calculation of the record length.
Valgrind issues will occur since initialization has not
happend for some bytes.
Fix
----
While creating the temporary table, the type of the field
needs to be to set FIELD_VARCHAR. This will allow myisam
to calculate the record length accurately.
This fix is a backport of BUG#13350136.
2ND EXECUTION OF PS
Description:
------------
When MySQL calls 'EXECUTE stmt' firstly to deal with ORDER BY clause which is
similar with 'ORDER BY 1,(t2a.f2+1)' in find_order_in_list(), it believes the
first expression is a position, the function replaces the pointer of the first
expression with Item_field object associated with a temporary table field,
then releases it after the end of the execution, that behavior destroys the
pointer of first expression.
After that, when MySQL calls 'EXECUTE stmt' once more, the first expression
points to an invalid pointer, so it crashed.
Fix:
----
If an item of ORDER clause is a location, reset 'args' with a original value.
Issue:
======
While re-preparing the statement in
Prepared_statement::swap_prepared_statement for swapping
the database of PS we only swapped the db string but not
its length. This resulted in mismatch between the actual
string and its length. In one particular case where db
of PS was dropped, we have db as null pointer and length
as non-zero. strdup which used above values resulted in
invalid memory access.
Solution:
=========
In Prepared_statement::swap_prepared_statement also swap
db_length along with db variable. Also, remove
DBUG_ASSERT(db_length == copy->db_length) as this have
no meaning if they are 2 different entities.
CRASHES IN WILD_CASE_COMPARE!
Description:- Executing FLUSH PRIVILEGES and REVOKE/
GRANT concurrently crashes the server.
Analysis:- Concurrent FLUSH PRIVILEGES and REVOKE/GRANT
might trigger a small time frame in which REVOKE/GRANT
fetches the "acl_proxy_user" information as a part of
"acl_check_proxy_grant_access()". Meanwhile FLUSH PRIVILEGES
deletes the old acl structures as a part of "acl_reload()".
After which REVOKE/GRANT tries to access the hostname in
"wild_case_compare()" which leads to a crash because of the
invalid memory access.
Fix:- Mutex lock on "acl_cache" is acquired before fetching
"acl_proxy_user" information in
"acl_check_proxy_grant_access()".
Issue:
======
The fulltext predicate is inside a subquery and involves
an outer reference; it thus cannot be used for FT index look-up,
but MySQL does not see it, which causes a illegal access.
Solution:
=========
Solution is backported from bug#21140088. Outer reference can
not be used as argument of the MATCH function. Added check for
outer reference.
When CHANGE MASTER was executed as a PS, its attributes were wrongly
getting reset toward the end of PREPARE. As a result, the subsequent
executions had no effect. Fixed by making sure that the CHANGE MASTER
attributes are preserved during the lifetime of the PS.
Problem was in rewriting left expression which had 2 references on it. Solved with making subselect reference main.
Item_in_optimized can have not Item_in_subselect reference in left part so type casting with no check is dangerous.
Item::cols() should be checked after Item::fix_fields().
CONVERT_CHARSET_PARTITION_CONSTANT:
SQL/SQL_PARTITION..CC:202
Issue:
-----
This problem happens under the following conditions:
1) A table partitioned with a character column as the key.
2) The expressions specified in the partition definition
requires a charset conversion. This can happen when the
server's default collation is different from the
expression's collation.
3) INSERT DELAYED is used to insert data into the table.
SOLUTION:
---------
While creating the delayed_insert object, initialize it
with the relevant select_lex.
UPDATE VIEW USING OUTER SUBQUERY
Issue:
-----
While resolving a column which refers to a table/view in an
outer query, it's respecitve item object is marked with the
outer query's select_lex object. But when the column refers
to a view or if the column is part of a subquery in the
HAVING clause, an Item_ref object is created. While the
reference to the outer query is stored by the Item_ref
object, the same is not stored in it's real_item.
This creates a problem with the IN-TO-EXISTS optmization.
When there is an index over the column in the inner query,
it will be considered since the column's real_item object
will be mistaken for a local field. This will lead to a
crash.
SOLUTION:
---------
Under the current design, the only way to fix this issue is
to check the reginfo.join_tab for a NULL value. If yes, the
query should not be worrying about the key use.
The testcase and comments added as part of the fix for
Bug#17766653 have been backported.