Skip to content

Commit fa9ab77

Browse files
committed
MDEV-36545: Possible crash in row_raw_format_str()
row_raw_format_str(): Treat the invalid value charset_coll==0 as binary. This could be invoked on FTS_%_CONFIG.key or SYS_FOREIGN.ID or possible other key columns. dtype_is_utf8(): Merge to its only caller row_raw_format_str(). row_raw_format(): Add debug assertions and comments to document when dtype_get_charset_coll(prtype) may be 0.
1 parent 3fd03e4 commit fa9ab77

File tree

3 files changed

+18
-44
lines changed

3 files changed

+18
-44
lines changed

storage/innobase/include/data0type.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -353,16 +353,6 @@ dtype_form_prtype(ulint old_prtype, ulint charset_coll)
353353
return(uint32_t(old_prtype + (charset_coll << 16)));
354354
}
355355

356-
/*********************************************************************//**
357-
Determines if a MySQL string type is a subset of UTF-8. This function
358-
may return false negatives, in case further character-set collation
359-
codes are introduced in MySQL later.
360-
@return whether a subset of UTF-8 */
361-
UNIV_INLINE
362-
bool
363-
dtype_is_utf8(
364-
/*==========*/
365-
ulint prtype);/*!< in: precise data type */
366356
/*********************************************************************//**
367357
Gets the type length.
368358
@return fixed length of the type, in bytes, or 0 if variable-length */

storage/innobase/include/data0type.inl

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,6 @@ Created 1/16/1996 Heikki Tuuri
2727
#include "mach0data.h"
2828
#include "ha_prototypes.h"
2929

30-
/*********************************************************************//**
31-
Determines if a MySQL string type is a subset of UTF-8. This function
32-
may return false negatives, in case further character-set collation
33-
codes are introduced in MySQL later.
34-
@return whether a subset of UTF-8 */
35-
UNIV_INLINE
36-
bool
37-
dtype_is_utf8(
38-
/*==========*/
39-
ulint prtype) /*!< in: precise data type */
40-
{
41-
/* These codes have been copied from strings/ctype-extra.c
42-
and strings/ctype-utf8.c. */
43-
switch (dtype_get_charset_coll(prtype)) {
44-
case 11: /* ascii_general_ci */
45-
case 65: /* ascii_bin */
46-
case 33: /* utf8_general_ci */
47-
case 83: /* utf8_bin */
48-
case 254: /* utf8_general_cs */
49-
return true;
50-
}
51-
52-
return false;
53-
}
54-
5530
/*********************************************************************//**
5631
Gets the MySQL type code from a dtype.
5732
@return MySQL type code; this is NOT an InnoDB type code! */

storage/innobase/row/row0row.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,18 +1407,18 @@ row_raw_format_str(
14071407

14081408
charset_coll = dtype_get_charset_coll(prtype);
14091409

1410-
if (UNIV_LIKELY(dtype_is_utf8(prtype))) {
1411-
1410+
switch (charset_coll) {
1411+
case 11: /* ascii_general_ci */
1412+
case 65: /* ascii_bin */
1413+
case 33: /* utf8_general_ci */
1414+
case 83: /* utf8_bin */
1415+
case 254: /* utf8_general_cs */
14121416
return(ut_str_sql_format(data, data_len, buf, buf_size));
1413-
}
1414-
/* else */
1415-
1416-
if (charset_coll == DATA_MYSQL_BINARY_CHARSET_COLL) {
1417-
1417+
case 0:
1418+
case DATA_MYSQL_BINARY_CHARSET_COLL:
14181419
*format_in_hex = TRUE;
14191420
return(0);
14201421
}
1421-
/* else */
14221422

14231423
return(innobase_raw_format(data, data_len, charset_coll,
14241424
buf, buf_size));
@@ -1479,9 +1479,18 @@ row_raw_format(
14791479
break;
14801480
case DATA_CHAR:
14811481
case DATA_VARCHAR:
1482+
/* FTS_%_CONFIG.key are incorrectly created with prtype==0.
1483+
The DATA_ENGLISH is being used for CHAR columns of the
1484+
InnoDB internal SQL parser, such as SYS_FOREIGN.ID.
1485+
For these, we will eventually goto format_in_hex. */
1486+
ut_ad(dtype_get_charset_coll(prtype) == 8
1487+
|| (mtype == DATA_VARCHAR
1488+
&& (prtype == 0 || prtype == DATA_ENGLISH)));
1489+
goto format_str;
14821490
case DATA_MYSQL:
14831491
case DATA_VARMYSQL:
1484-
1492+
ut_ad(dtype_get_charset_coll(prtype));
1493+
format_str:
14851494
ret = row_raw_format_str(data, data_len, prtype,
14861495
buf, buf_size, &format_in_hex);
14871496
if (format_in_hex) {

0 commit comments

Comments
 (0)