Problem was that created table was not marked as used (not set query_id) and so opening tables for stored function pick it up (as opened place holder for it) and used changing TABLE internals.
The select mentioned in the bug attempted to create a temporary table
using the maria storage engine. The table needs to have primary keys such that
duplicates can be removed. Unfortunately this use case has a longer
than allowed key and the tmp table got created without a temporary key.
We must not allow materialization for the subquery if the total key
length and key parts is greater than what the storage engine supports.
When one evaluates row-based comparison like (X, Y) = (A,B), one should
first call bring_value() for the Item that returns row value. If you
don't do that and just attempt to read values of X and Y, you get stale
values.
Semi-join/Materialization can take a row-based comparison apart and
make ref access from it. In that case, we need to call bring_value()
to get the index lookup components.
Consider a query with subquery in form t.key=(select ...). Suppose, the
parent query uses this equality for ref access.
It will attempt to evaluate the subquery in get_best_combination(),
right before the join->join_tab[...] array is filled. The problem was
that subquery optimization will attempt to look at parent's join->join_tab
to check how many times subquery will be executed (and crash).
Fixed by not doing that when the subquery is constant (non-constant
subqueries are only be evaluated during join execution, so they are not
affected)
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.