diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 125e265c1e7..d43b1c79f1f 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -207,7 +207,7 @@ static char TMPDIR[FN_REFLEN]; static char global_subst_from[200]; static char global_subst_to[200]; static char *global_subst= NULL; -static char *read_command_buf= NULL; +static char *read_command_buf= NULL, *read_command_buf_end; static MEM_ROOT require_file_root; static const my_bool my_true= 1; static const my_bool my_false= 0; @@ -3866,9 +3866,24 @@ end: #endif if (error) { - uint status= WEXITSTATUS(error); + uint status; int i; +#ifdef _WIN32 + status= WEXITSTATUS(error); +#else + /* WEXITSTATUS() is only valid for a normal exit; a process killed by an + uncaught signal must be translated using the shell's 128+signal + convention, or the real error is silently lost as status 0. */ + if (WIFEXITED(error)) + status= WEXITSTATUS(error); + else if (WIFSIGNALED(error)) + status= 128 + WTERMSIG(error); + else + status= error; + +#endif + if (command->abort_on_error) { report_or_die("exec of '%s' failed, error: %d, status: %d, errno: %d\n" @@ -5602,7 +5617,7 @@ static void primary(Expression_value *result, const char **s) enum func_type func_type= get_expr_function_type(start, end - start); if (func_type == FUNC_UNKNOWN) - die("Syntax error: Unknown function"); + die("Syntax error: Unknown function '%.*s'", (int) (end - start), start); *s= end + 1; // skip '(' handle_expr_function_call(func_type, result, s); @@ -6049,47 +6064,48 @@ static void expr(Expression_value *result, const char **s) static struct { const char *name; + size_t length; enum func_type type; } function_table[]= { // Numeric functions - {"abs", FUNC_ABS}, - {"bin", FUNC_BIN}, - {"conv", FUNC_CONV}, - {"hex", FUNC_HEX}, - {"oct", FUNC_OCT}, + {STRING_WITH_LEN("abs"), FUNC_ABS}, + {STRING_WITH_LEN("bin"), FUNC_BIN}, + {STRING_WITH_LEN("conv"), FUNC_CONV}, + {STRING_WITH_LEN("hex"), FUNC_HEX}, + {STRING_WITH_LEN("oct"), FUNC_OCT}, // String functions - {"concat", FUNC_CONCAT}, - {"concat_ws", FUNC_CONCAT_WS}, - {"greatest", FUNC_GREATEST}, - {"insert", FUNC_INSERT}, - {"instr", FUNC_INSTR}, - {"lcase", FUNC_LOWER}, - {"least", FUNC_LEAST}, - {"length", FUNC_LENGTH}, - {"locate", FUNC_LOCATE}, - {"lower", FUNC_LOWER}, - {"lpad", FUNC_LPAD}, - {"ltrim", FUNC_LTRIM}, - {"repeat", FUNC_REPEAT}, - {"replace", FUNC_REPLACE}, - {"reverse", FUNC_REVERSE}, - {"rpad", FUNC_RPAD}, - {"rtrim", FUNC_RTRIM}, - {"substr", FUNC_SUBSTR}, - {"substring", FUNC_SUBSTR}, - {"substring_index", FUNC_SUBSTR_IDX}, - {"trim", FUNC_TRIM}, - {"ucase", FUNC_UPPER}, - {"upper", FUNC_UPPER}, + {STRING_WITH_LEN("concat"), FUNC_CONCAT}, + {STRING_WITH_LEN("concat_ws"), FUNC_CONCAT_WS}, + {STRING_WITH_LEN("greatest"), FUNC_GREATEST}, + {STRING_WITH_LEN("insert"), FUNC_INSERT}, + {STRING_WITH_LEN("instr"), FUNC_INSTR}, + {STRING_WITH_LEN("lcase"), FUNC_LOWER}, + {STRING_WITH_LEN("least"), FUNC_LEAST}, + {STRING_WITH_LEN("length"), FUNC_LENGTH}, + {STRING_WITH_LEN("locate"), FUNC_LOCATE}, + {STRING_WITH_LEN("lower"), FUNC_LOWER}, + {STRING_WITH_LEN("lpad"), FUNC_LPAD}, + {STRING_WITH_LEN("ltrim"), FUNC_LTRIM}, + {STRING_WITH_LEN("repeat"), FUNC_REPEAT}, + {STRING_WITH_LEN("replace"), FUNC_REPLACE}, + {STRING_WITH_LEN("reverse"), FUNC_REVERSE}, + {STRING_WITH_LEN("rpad"), FUNC_RPAD}, + {STRING_WITH_LEN("rtrim"), FUNC_RTRIM}, + {STRING_WITH_LEN("substr"), FUNC_SUBSTR}, + {STRING_WITH_LEN("substring"), FUNC_SUBSTR}, + {STRING_WITH_LEN("substring_index"), FUNC_SUBSTR_IDX}, + {STRING_WITH_LEN("trim"), FUNC_TRIM}, + {STRING_WITH_LEN("ucase"), FUNC_UPPER}, + {STRING_WITH_LEN("upper"), FUNC_UPPER}, // Regexp functions - {"regexp_instr", FUNC_REGEXP_INSTR}, - {"regexp_replace", FUNC_REGEXP_REPLACE}, - {"regexp_substr", FUNC_REGEXP_SUBSTR}, + {STRING_WITH_LEN("regexp_instr"), FUNC_REGEXP_INSTR}, + {STRING_WITH_LEN("regexp_replace"), FUNC_REGEXP_REPLACE}, + {STRING_WITH_LEN("regexp_substr"), FUNC_REGEXP_SUBSTR}, // Null functions - {"coalesce", FUNC_COALESCE}, - {"ifnull", FUNC_IFNULL}, - {"nullif", FUNC_NULLIF}, - {NULL, FUNC_UNKNOWN} + {STRING_WITH_LEN("coalesce"), FUNC_COALESCE}, + {STRING_WITH_LEN("ifnull"), FUNC_IFNULL}, + {STRING_WITH_LEN("nullif"), FUNC_NULLIF}, + {NULL, 0, FUNC_UNKNOWN} }; @@ -6329,9 +6345,9 @@ void func_oct(Expression_value args[], int count, Expression_value *result) @param[out] result Expression_value to store result @details - Converts a number to hexadecimal representation. HEX(N) returns a string representation of the hexadecimal value of N. This is equivalent to CONV(N, 10, 16). + HEX(str) returns a hexadecimal representation of the bytes of str. @note Dies if argument count != 1 */ @@ -6341,7 +6357,15 @@ void func_hex(Expression_value args[], int count, Expression_value *result) if (count != 1) die("hex() expects 1 argument, got %d", count); - convert_base_helper(args[0].to_string(), 10, 16, result); + if (args[0].is_numeric) + convert_base_helper(args[0].to_string(), 10, 16, result); + else + { + My_string str= args[0].to_string(); + My_string hex_str; + hex_str.set_hex(str.ptr(), str.length()); + result->set_string(hex_str.ptr(), hex_str.length()); + } } @@ -7605,7 +7629,8 @@ enum func_type get_expr_function_type(const char *name, size_t len) { for (int i= 0; function_table[i].name; ++i) { - if (!strncasecmp(function_table[i].name, name, len)) + if (function_table[i].length == len && + !strncasecmp(function_table[i].name, name, len)) return function_table[i].type; } return FUNC_UNKNOWN; @@ -9687,7 +9712,7 @@ int read_line() *p= 0; DBUG_PRINT("exit", ("Found delimiter '%s' at line %d", delimiter, cur_file->lineno)); - DBUG_RETURN(0); + goto ret; } else if ((c == '{' && (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5, @@ -9700,7 +9725,7 @@ int read_line() *p= 0; DBUG_PRINT("exit", ("Found '{' indicating start of block at line %d", cur_file->lineno)); - DBUG_RETURN(0); + goto ret; } else if (c == '\'' || c == '"' || c == '`') { @@ -9734,7 +9759,7 @@ int read_line() *p= 0; DBUG_PRINT("exit", ("Found newline in comment at line: %d", cur_file->lineno)); - DBUG_RETURN(0); + goto ret; } break; @@ -9754,7 +9779,7 @@ int read_line() DBUG_PRINT("info", ("Found two new lines in a row")); *p++= c; *p= 0; - DBUG_RETURN(0); + goto ret; } /* Query hasn't started yet */ @@ -9771,7 +9796,7 @@ int read_line() *p= 0; DBUG_PRINT("exit", ("Found delimiter '%s' at line: %d", delimiter, cur_file->lineno)); - DBUG_RETURN(0); + goto ret; } else if (c == '}') { @@ -9780,7 +9805,7 @@ int read_line() *p= 0; DBUG_PRINT("exit", ("Found '}' in beginning of a line at line: %d", cur_file->lineno)); - DBUG_RETURN(0); + goto ret; } else if (c == '\'' || c == '"' || c == '`') { @@ -9839,6 +9864,8 @@ int read_line() } } } +ret: + read_command_buf_end= p; DBUG_RETURN(0); } @@ -9854,14 +9881,13 @@ int read_line() */ -void convert_to_format_v1(char* query) +void convert_to_format_v1(char* query, char **end) { int last_c_was_quote= 0; char *p= query, *to= query; - char *end= strend(query); char last_c; - while (p <= end) + while (p <= *end) { if (*p == '\n' && !last_c_was_quote) { @@ -9892,6 +9918,7 @@ void convert_to_format_v1(char* query) last_c_was_quote= 0; } } + *end= to; } @@ -10008,9 +10035,9 @@ int read_command(struct st_command** command_ptr) } if (opt_result_format_version == 1) - convert_to_format_v1(read_command_buf); + convert_to_format_v1(read_command_buf, &read_command_buf_end); - char *p= read_command_buf; + char *p= read_command_buf, *end= read_command_buf_end; DBUG_PRINT("info", ("query: '%s'", read_command_buf)); if (*p == '#') { @@ -10027,29 +10054,32 @@ int read_command(struct st_command** command_ptr) } /* Skip leading spaces */ - while (*p && my_isspace(charset_info, *p)) + while (p < end && my_isspace(charset_info, *p)) p++; - if (!(command->query_buf= command->query= my_strdup(PSI_NOT_INSTRUMENTED, p, MYF(MY_WME)))) + if (!(command->query_buf= command->query= + (char*)my_memdup(PSI_NOT_INSTRUMENTED, p, end - p, MYF(MY_WME)))) die("Out of memory"); + command->query_len= (int)(end - p - 1); + command->end= command->query + command->query_len; + p= command->query; + end= command->end; /* Calculate first word length(the command), terminated - by 'space' , '(' or 'delimiter' */ - p= command->query; - while (*p && !my_isspace(charset_info, *p) && *p != '(' && !is_delimiter(p)) + by 'space' , '(' or 'delimiter' + */ + while (p < end && !my_isspace(charset_info, *p) && *p != '(' && !is_delimiter(p)) p++; command->first_word_len= (uint) (p - command->query); DBUG_PRINT("info", ("first_word: %.*s", command->first_word_len, command->query)); /* Skip spaces between command and first argument */ - while (*p && my_isspace(charset_info, *p)) + while (p < end && my_isspace(charset_info, *p)) p++; command->first_argument= p; - command->end= strend(command->query); - command->query_len= (int)(command->end - command->query); parser.read_lines++; DBUG_RETURN(0); } @@ -12351,7 +12381,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) else { query = command->query; - query_len = strlen(query); + query_len = command->query_len; } /* @@ -12741,6 +12771,7 @@ void get_command_type(struct st_command* command) if (type == Q_QUERY) { /* Skip the "query" part */ + command->query_len-= (int)(command->first_argument - command->query); command->query= command->first_argument; } } @@ -13312,7 +13343,8 @@ int main(int argc, char **argv) if (command->query == command->query_buf) { /* Skip the first part of command, i.e query_xxx */ - command->query= command->first_argument; + command->query_len-= (int)(command->first_argument - command->query); + command->query= command->first_argument; command->first_word_len= 0; } /* fall through */ @@ -13374,7 +13406,10 @@ int main(int argc, char **argv) /* Remove "send" if this is first iteration */ if (command->query == command->query_buf) + { + command->query_len-= (int)(command->first_argument - command->query); command->query= command->first_argument; + } /* run_query() can execute a query partially, depending on the flags. diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 706a8156095..82d437fc1b8 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -248,7 +248,7 @@ IF(WITH_WSREP) SETA(CPACK_RPM_server_PACKAGE_REQUIRES "galera-4" "rsync" "grep" "gawk" "iproute" "coreutils" "findutils" "tar") - SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "socat" "pv") + SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "socat" "pv" "stunnel") SETA(CPACK_RPM_test_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" "socat") ENDIF() diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 9410bc7a48a..1ebf5013730 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -64,6 +64,9 @@ # # - INSTALL_UNIX_ADDRDIR (path to mysql.sock) # +# - INSTALL_RUNDIR (runtime state files that mariadbd must not write, +# e.g. what systemd reads as EnvironmentFile) +# IF(NOT INSTALL_LAYOUT) IF(DEB) @@ -163,7 +166,7 @@ SET(INSTALL_UNIX_ADDRDIR_RPM "${INSTALL_MYSQLDATADIR_RPM}/mysql.sock" SET(INSTALL_SYSTEMD_UNITDIR_RPM "/usr/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_RPM "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_RPM "/usr/lib/tmpfiles.d") -SET(INSTALL_RUNDATADIR_RPM "/run/mariadb") +SET(INSTALL_RUNDIR_RPM "/run") SET(INSTALL_PAMDIR_RPM "/${INSTALL_LIBDIR_RPM}/security") SET(INSTALL_PAMDATADIR_RPM "/etc/security") @@ -194,8 +197,8 @@ SET(INSTALL_SUPPORTFILESDIR_DEB "share/mysql") # SET(INSTALL_MYSQLDATADIR_DEB "/var/lib/mysql") -SET(INSTALL_RUNDATADIR_DEB "/run/mysqld") -SET(INSTALL_UNIX_ADDRDIR_DEB "${INSTALL_RUNDATADIR_DEB}/mysqld.sock") +SET(INSTALL_RUNDIR_DEB "/run") +SET(INSTALL_UNIX_ADDRDIR_DEB "${INSTALL_RUNDIR_DEB}/mysqld/mysqld.sock") SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d") @@ -259,7 +262,10 @@ IF(NOT MYSQL_UNIX_ADDR) SET(MYSQL_UNIX_ADDR ${INSTALL_UNIX_ADDRDIR}) ENDIF() -IF(NOT INSTALL_RUNDATADIR) +IF(NOT INSTALL_RUNDIR) + # No /run in a tarball installation - fall back to the socket directory. + # Note that mariadbd can write there, so the isolation that /run gives to + # packages (see EnvironmentFile= in mariadb.service) is not achieved. get_filename_component(MYSQL_UNIX_DIR ${MYSQL_UNIX_ADDR} DIRECTORY) - SET(INSTALL_RUNDATADIR "${MYSQL_UNIX_DIR}" CACHE FILEPATH "Rundata installation directory" ${FORCE}) + SET(INSTALL_RUNDIR "${MYSQL_UNIX_DIR}" CACHE FILEPATH "Runtime state directory" ${FORCE}) ENDIF() diff --git a/debian/control b/debian/control index 5810bb1e4c0..e9788e5ceb6 100644 --- a/debian/control +++ b/debian/control @@ -676,7 +676,8 @@ Architecture: any Suggests: mariadb-test, netcat-openbsd Recommends: libhtml-template-perl, - pv + pv, + stunnel Pre-Depends: adduser (>= 3.40), debconf, mariadb-common (>= ${source:Version}) diff --git a/libmariadb b/libmariadb index 93bb9266666..35c41cddb3c 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 93bb9266666a0a838187679ad2cc14af169895da +Subproject commit 35c41cddb3c16e9d80dee55158a59118a8fd831d diff --git a/mysql-test/main/alter_table_combinations.result b/mysql-test/main/alter_table_combinations.result index cbf98f620ef..7eeb97d659d 100644 --- a/mysql-test/main/alter_table_combinations.result +++ b/mysql-test/main/alter_table_combinations.result @@ -321,4 +321,13 @@ drop table t1; # # End of 10.5 tests # +# +# MDEV-31808 Server crash upon altering table with NEXTVAL for default under exclusive lock +# +CREATE SEQUENCE s ENGINE=Aria; +CREATE TABLE t (a INT DEFAULT(NEXTVAL(s)), b INT); +ALTER TABLE t FORCE, ALGORITHM=COPY, LOCK=EXCLUSIVE; +DROP TABLE t; +DROP SEQUENCE s; +# End of 10.6 tests set @@default_storage_engine= @save_default_engine; diff --git a/mysql-test/main/alter_table_combinations.test b/mysql-test/main/alter_table_combinations.test index 7c8d7f42096..b208f0e4416 100644 --- a/mysql-test/main/alter_table_combinations.test +++ b/mysql-test/main/alter_table_combinations.test @@ -260,4 +260,18 @@ drop table t1; --echo # End of 10.5 tests --echo # +--echo # +--echo # MDEV-31808 Server crash upon altering table with NEXTVAL for default under exclusive lock +--echo # + +CREATE SEQUENCE s ENGINE=Aria; +CREATE TABLE t (a INT DEFAULT(NEXTVAL(s)), b INT); +ALTER TABLE t FORCE, ALGORITHM=COPY, LOCK=EXCLUSIVE; + +# Cleanup +DROP TABLE t; +DROP SEQUENCE s; + +--echo # End of 10.6 tests + set @@default_storage_engine= @save_default_engine; diff --git a/mysql-test/main/gis-json.result b/mysql-test/main/gis-json.result index 49ec7739458..912fb405327 100644 --- a/mysql-test/main/gis-json.result +++ b/mysql-test/main/gis-json.result @@ -110,6 +110,8 @@ Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array. SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }") as exp; exp NULL +Warnings: +Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function. SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')) as exp; exp NULL @@ -135,7 +137,126 @@ repeat(']}', 2000) exp NULL Warnings: -Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 473 +Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 688 +# Boundary condition: foreign-member nesting at depth 32 +SET @geom := '{"type":"Point","coordinates":[1,2]}'; +SET @doc := CONCAT( +REPEAT('{"x":', 29), +@geom, +REPEAT('}', 29) +); +SELECT ST_ASTEXT( ST_GeomFromGeoJSON(@doc) ) AS expr; +expr +NULL +Warnings: +Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function. +# Foreign-member nesting exceeds depth 32 +SET @geom := '{"type":"Point","coordinates":[1,2]}'; +SET @doc := CONCAT( +REPEAT('{"x":', 30), +@geom, +REPEAT('}', 30) +); +SELECT ST_GeomFromGeoJSON(@doc) AS expr; +expr +NULL +Warnings: +Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 181 +# Deep foreign member attached to otherwise valid GeoJSON +SET @foreign := CONCAT( +REPEAT('{"x":', 28), +'{"leaf":1}', +REPEAT('}', 28) +); +SET @doc := CONCAT( +'{"type":"Point","coordinates":[10,20],"foreign":', +@foreign, +'}' +); +SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr; +expr +POINT(10 20) +# Foreign member exceeds depth limit +SET @foreign := CONCAT( +REPEAT('{"x":', 29), +'{"leaf":1}', +REPEAT('}', 29) +); +SET @doc := CONCAT( +'{"type":"Point","coordinates":[10,20],"foreign":', +@foreign, +'}' +); +SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr; +expr +POINT(10 20) +# GeometryCollection containing 33 valid GeoJSON Point objects +SET @point := '{"type":"Point","coordinates":[1,2]}'; +SET @geoms := CONCAT( +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point, ',', @point, ',', @point, ',', +@point, ',', @point, ',', @point +); +SET @doc := CONCAT( +'{"type":"GeometryCollection","geometries":[', +@geoms, +']}' +); +SELECT ST_AsText(ST_GeomFromGeoJSON(@doc)) AS expr; +expr +GEOMETRYCOLLECTION(POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2)) +# +# MDEV-39981: ST_GEOMFROMGEOJSON returns wrong result with reversed key order +# +# GeometryCollection: type before geometries (baseline) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type":"GeometryCollection","geometries":[]}')) as expr; +expr +GEOMETRYCOLLECTION EMPTY +# GeometryCollection: geometries before type (empty) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[],"type":"GeometryCollection"}')) as expr; +expr +GEOMETRYCOLLECTION EMPTY +# GeometryCollection: geometries before type (non-empty) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[0,1]}],"type":"GeometryCollection"}')) as expr; +expr +GEOMETRYCOLLECTION(POINT(0 1)) +# GeometryCollection: multiple geometries before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[1,2]},{"type":"Point","coordinates":[3,4]}],"type":"GeometryCollection"}')) as expr; +expr +GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4)) +# Point: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[0,1],"type":"Point"}')) as expr; +expr +POINT(0 1) +# LineString: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[0,0],[1,1],[2,2]],"type":"LineString"}')) as expr; +expr +LINESTRING(0 0,1 1,2 2) +# Polygon: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[[0,0],[1,0],[1,1],[0,1],[0,0]]],"type":"Polygon"}')) as expr; +expr +POLYGON((0 0,1 0,1 1,0 1,0 0)) +# FeatureCollection: features before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"features":[{"geometry":{"type":"Point","coordinates":[5,6]},"type":"Feature","properties":{}}],"type":"FeatureCollection"}')) as expr; +expr +GEOMETRYCOLLECTION(POINT(5 6)) +# Feature: geometry before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometry":{"coordinates":[7,8],"type":"Point"},"type":"Feature","properties":{}}')) as expr; +expr +POINT(7 8) +# Unknown keys interspersed (should be ignored) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"foo":"bar","geometries":[],"type":"GeometryCollection","extra":123}')) as expr; +expr +GEOMETRYCOLLECTION EMPTY +# Deeply nested geometries before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"geometries":[{"type":"Point","coordinates":[9,10]}],"type":"GeometryCollection"}],"type":"GeometryCollection"}')) as expr; +expr +GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(9 10))) # End of 10.6 tests # # MDEV-34079: ST_AsGeoJSON returns incorrect value for empty geometry diff --git a/mysql-test/main/gis-json.test b/mysql-test/main/gis-json.test index ca402d1c2ef..dbbf7b7f667 100644 --- a/mysql-test/main/gis-json.test +++ b/mysql-test/main/gis-json.test @@ -70,6 +70,120 @@ SELECT ST_GeomFromGeoJSON( repeat(']}', 2000) )) as exp; +--echo # Boundary condition: foreign-member nesting at depth 32 +SET @geom := '{"type":"Point","coordinates":[1,2]}'; + +SET @doc := CONCAT( + REPEAT('{"x":', 29), + @geom, + REPEAT('}', 29) +); + +SELECT ST_ASTEXT( ST_GeomFromGeoJSON(@doc) ) AS expr; + + +--echo # Foreign-member nesting exceeds depth 32 +SET @geom := '{"type":"Point","coordinates":[1,2]}'; + +SET @doc := CONCAT( + REPEAT('{"x":', 30), + @geom, + REPEAT('}', 30) +); + +SELECT ST_GeomFromGeoJSON(@doc) AS expr; + + +--echo # Deep foreign member attached to otherwise valid GeoJSON +SET @foreign := CONCAT( + REPEAT('{"x":', 28), + '{"leaf":1}', + REPEAT('}', 28) +); + +SET @doc := CONCAT( + '{"type":"Point","coordinates":[10,20],"foreign":', + @foreign, + '}' +); + +SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr; + + +--echo # Foreign member exceeds depth limit +SET @foreign := CONCAT( + REPEAT('{"x":', 29), + '{"leaf":1}', + REPEAT('}', 29) +); + +SET @doc := CONCAT( + '{"type":"Point","coordinates":[10,20],"foreign":', + @foreign, + '}' +); + +SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr; + +--echo # GeometryCollection containing 33 valid GeoJSON Point objects +SET @point := '{"type":"Point","coordinates":[1,2]}'; + +SET @geoms := CONCAT( + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point, ',', @point, ',', @point, ',', + @point, ',', @point, ',', @point +); + +SET @doc := CONCAT( + '{"type":"GeometryCollection","geometries":[', + @geoms, + ']}' +); + +SELECT ST_AsText(ST_GeomFromGeoJSON(@doc)) AS expr; + +--echo # +--echo # MDEV-39981: ST_GEOMFROMGEOJSON returns wrong result with reversed key order +--echo # + +--echo # GeometryCollection: type before geometries (baseline) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type":"GeometryCollection","geometries":[]}')) as expr; + +--echo # GeometryCollection: geometries before type (empty) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[],"type":"GeometryCollection"}')) as expr; + +--echo # GeometryCollection: geometries before type (non-empty) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[0,1]}],"type":"GeometryCollection"}')) as expr; + +--echo # GeometryCollection: multiple geometries before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[1,2]},{"type":"Point","coordinates":[3,4]}],"type":"GeometryCollection"}')) as expr; + +--echo # Point: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[0,1],"type":"Point"}')) as expr; + +--echo # LineString: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[0,0],[1,1],[2,2]],"type":"LineString"}')) as expr; + +--echo # Polygon: coordinates before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[[0,0],[1,0],[1,1],[0,1],[0,0]]],"type":"Polygon"}')) as expr; + +--echo # FeatureCollection: features before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"features":[{"geometry":{"type":"Point","coordinates":[5,6]},"type":"Feature","properties":{}}],"type":"FeatureCollection"}')) as expr; + +--echo # Feature: geometry before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometry":{"coordinates":[7,8],"type":"Point"},"type":"Feature","properties":{}}')) as expr; + +--echo # Unknown keys interspersed (should be ignored) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"foo":"bar","geometries":[],"type":"GeometryCollection","extra":123}')) as expr; + +--echo # Deeply nested geometries before type +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"geometries":[{"type":"Point","coordinates":[9,10]}],"type":"GeometryCollection"}],"type":"GeometryCollection"}')) as expr; + --echo # End of 10.6 tests --echo # diff --git a/mysql-test/main/grant5.result b/mysql-test/main/grant5.result index d67e3443fe3..941afe73a73 100644 --- a/mysql-test/main/grant5.result +++ b/mysql-test/main/grant5.result @@ -494,6 +494,34 @@ CREATE USER for u2@localhost CREATE USER `u2`@`localhost` IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' drop user u1@localhost; drop user u2@localhost; +# +# MDEV-40541 role vs user@localhost acl_cache key confusion +# +create database db; +create table db.t1(a varchar(40)); +insert into db.t1 values ('role-cache-collision-row'); +create role r1; +create user r1@localhost identified by 'r1pass'; +create user u1@'127.0.0.1' identified by 'u1pass'; +grant select on db.* to r1@localhost; +grant r1 to u1@'127.0.0.1'; +connect r1,localhost,r1,r1pass; +select a as precache from db.t1; +precache +role-cache-collision-row +connect u1,127.0.0.1,u1,u1pass; +set role r1; +show grants; +Grants for u1@127.0.0.1 +GRANT `r1` TO `u1`@`127.0.0.1` +GRANT USAGE ON *.* TO `u1`@`127.0.0.1` IDENTIFIED BY PASSWORD '*4C5C0A2C80D7567C7CFBDFC09409901AADC4B390' +GRANT USAGE ON *.* TO `r1` +select a from db.t1; +ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `db`.`t1` +connection default; +drop database db; +drop role r1; +drop user r1@localhost, u1@'127.0.0.1'; # End of 10.6 tests # # MDEV-37256: The permission check of LOAD INDEX INTO CACHE and CACHE INDEX is broken diff --git a/mysql-test/main/grant5.test b/mysql-test/main/grant5.test index 249bb5790d0..62f538145e0 100644 --- a/mysql-test/main/grant5.test +++ b/mysql-test/main/grant5.test @@ -455,6 +455,35 @@ show create user u2@localhost; drop user u1@localhost; drop user u2@localhost; +--echo # +--echo # MDEV-40541 role vs user@localhost acl_cache key confusion +--echo # +create database db; +create table db.t1(a varchar(40)); +insert into db.t1 values ('role-cache-collision-row'); + +create role r1; +create user r1@localhost identified by 'r1pass'; +create user u1@'127.0.0.1' identified by 'u1pass'; + +grant select on db.* to r1@localhost; +grant r1 to u1@'127.0.0.1'; +#flush privileges; + +connect r1,localhost,r1,r1pass; +select a as precache from db.t1; + +connect u1,127.0.0.1,u1,u1pass; +set role r1; +show grants; +--error ER_TABLEACCESS_DENIED_ERROR +select a from db.t1; + +connection default; +drop database db; +drop role r1; +drop user r1@localhost, u1@'127.0.0.1'; + --echo # End of 10.6 tests --echo # diff --git a/mysql-test/main/intersect_all.result b/mysql-test/main/intersect_all.result index 966053c7c98..28268655074 100644 --- a/mysql-test/main/intersect_all.result +++ b/mysql-test/main/intersect_all.result @@ -1356,3 +1356,69 @@ a b 1 2 drop tables t1, t2, t3; set sql_mode= default; +# +# MDEV-38722 server crash hp_rec_key_cmp +# +# original reproducer (used to crash), returns a single row +SELECT 1 INTERSECT SELECT 1 UNION ALL SELECT 1 EXCEPT ALL SELECT 1; +1 +1 +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(1),(2),(3); +CREATE TABLE t2 (i INT); +INSERT INTO t2 VALUES (1),(2),(2); +CREATE TABLE t3 (i INT); +INSERT INTO t3 VALUES (1),(3); +SELECT i FROM t1 INTERSECT SELECT i FROM t3 +UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3 ORDER BY i; +i +1 +2 +2 +(((SELECT i FROM t1) INTERSECT (SELECT i FROM t3)) UNION ALL (SELECT i FROM t2)) +EXCEPT ALL (SELECT i FROM t3) ORDER BY i; +i +1 +2 +2 +# trailing UNION ALL after the EXCEPT ALL +SELECT i FROM t1 INTERSECT SELECT i FROM t2 UNION ALL SELECT i FROM t2 +EXCEPT ALL SELECT i FROM t3 UNION ALL SELECT i FROM t1 ORDER BY i; +i +1 +1 +1 +2 +2 +2 +2 +3 +((((SELECT i FROM t1) INTERSECT (SELECT i FROM t2)) UNION ALL (SELECT i FROM t2)) +EXCEPT ALL (SELECT i FROM t3)) UNION ALL (SELECT i FROM t1) ORDER BY i; +i +1 +1 +1 +2 +2 +2 +2 +3 +# a leading INTERSECT ALL keeps the operation extended while the last +# INTERSECT DISTINCT node is the index-release point +SELECT i FROM t1 INTERSECT ALL SELECT i FROM t2 INTERSECT SELECT i FROM t3 +UNION ALL SELECT i FROM t2 ORDER BY i; +i +1 +1 +2 +2 +(((SELECT i FROM t1) INTERSECT ALL (SELECT i FROM t2)) INTERSECT (SELECT i FROM t3)) +UNION ALL (SELECT i FROM t2) ORDER BY i; +i +1 +1 +2 +2 +DROP TABLE t1,t2,t3; +# End of 10.6 tests diff --git a/mysql-test/main/intersect_all.test b/mysql-test/main/intersect_all.test index c3dc4e123f0..75d08182f80 100644 --- a/mysql-test/main/intersect_all.test +++ b/mysql-test/main/intersect_all.test @@ -497,3 +497,34 @@ select * from t1 except all select * from t2 intersect all select * from t1 unio select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2 order by a desc limit 3; drop tables t1, t2, t3; set sql_mode= default; + +--echo # +--echo # MDEV-38722 server crash hp_rec_key_cmp +--echo # +--echo # original reproducer (used to crash), returns a single row +SELECT 1 INTERSECT SELECT 1 UNION ALL SELECT 1 EXCEPT ALL SELECT 1; + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(1),(2),(3); +CREATE TABLE t2 (i INT); +INSERT INTO t2 VALUES (1),(2),(2); +CREATE TABLE t3 (i INT); +INSERT INTO t3 VALUES (1),(3); +SELECT i FROM t1 INTERSECT SELECT i FROM t3 + UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3 ORDER BY i; +(((SELECT i FROM t1) INTERSECT (SELECT i FROM t3)) UNION ALL (SELECT i FROM t2)) + EXCEPT ALL (SELECT i FROM t3) ORDER BY i; +--echo # trailing UNION ALL after the EXCEPT ALL +SELECT i FROM t1 INTERSECT SELECT i FROM t2 UNION ALL SELECT i FROM t2 + EXCEPT ALL SELECT i FROM t3 UNION ALL SELECT i FROM t1 ORDER BY i; +((((SELECT i FROM t1) INTERSECT (SELECT i FROM t2)) UNION ALL (SELECT i FROM t2)) + EXCEPT ALL (SELECT i FROM t3)) UNION ALL (SELECT i FROM t1) ORDER BY i; +--echo # a leading INTERSECT ALL keeps the operation extended while the last +--echo # INTERSECT DISTINCT node is the index-release point +SELECT i FROM t1 INTERSECT ALL SELECT i FROM t2 INTERSECT SELECT i FROM t3 + UNION ALL SELECT i FROM t2 ORDER BY i; +(((SELECT i FROM t1) INTERSECT ALL (SELECT i FROM t2)) INTERSECT (SELECT i FROM t3)) + UNION ALL (SELECT i FROM t2) ORDER BY i; +DROP TABLE t1,t2,t3; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/lotofstack.result b/mysql-test/main/lotofstack.result index 6f776eb6733..eb51ccd8e04 100644 --- a/mysql-test/main/lotofstack.result +++ b/mysql-test/main/lotofstack.result @@ -103,4 +103,16 @@ drop table t3| # MDEV-40409 ST_GeomFromText stack overrun on deeply nested GeometryCollection # SELECT ST_GeomFromText(CONCAT(REPEAT('GEOMETRYCOLLECTION(',5000),'POINT(1 1)',REPEAT(')',5000))); +# +# MDEV-40540 ST_GeomFromWKB stack overrun on deeply nested GeometryCollection +# +set @a=concat(0x0107000000, repeat(0x010000000107000000, 120000), 0x00000000); +SELECT ST_GeomFromWKB(@a); +# +# MDEV-39750 ExtractValue does not control recursion depth. +# +SELECT ExtractValue('', REPEAT('(', 100000)); +ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. +SELECT ExtractValue('', REPEAT('/n', 100000)); +ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. # End of 10.6 tests diff --git a/mysql-test/main/lotofstack.test b/mysql-test/main/lotofstack.test index 20d9789b99c..b8ce7f566c4 100644 --- a/mysql-test/main/lotofstack.test +++ b/mysql-test/main/lotofstack.test @@ -147,4 +147,24 @@ delimiter ;| SELECT ST_GeomFromText(CONCAT(REPEAT('GEOMETRYCOLLECTION(',5000),'POINT(1 1)',REPEAT(')',5000))); --enable_result_log +--echo # +--echo # MDEV-40540 ST_GeomFromWKB stack overrun on deeply nested GeometryCollection +--echo # +set @a=concat(0x0107000000, repeat(0x010000000107000000, 120000), 0x00000000); +--disable_result_log +--error ER_STACK_OVERRUN_NEED_MORE +SELECT ST_GeomFromWKB(@a); +--enable_result_log + +--echo # +--echo # MDEV-39750 ExtractValue does not control recursion depth. +--echo # +--replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/ +--error ER_STACK_OVERRUN_NEED_MORE +SELECT ExtractValue('', REPEAT('(', 100000)); + +--replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/ +--error ER_STACK_OVERRUN_NEED_MORE +SELECT ExtractValue('', REPEAT('/n', 100000)); + --echo # End of 10.6 tests diff --git a/mysql-test/main/mdev-37000.result b/mysql-test/main/mdev-37000.result new file mode 100644 index 00000000000..73e6812382a --- /dev/null +++ b/mysql-test/main/mdev-37000.result @@ -0,0 +1,8 @@ +# +# MDEV-37000 Deleting a row from Aria table results to 'Index is corrupt' +# +CREATE OR REPLACE TABLE t (a INT, b CHAR(8) NOT NULL, KEY(b)) ENGINE=Aria DEFAULT CHARSET=utf8; +INSERT INTO t VALUES (1,'20070101'), (2,'20070101'); +DELETE FROM t LIMIT 2; +DROP TABLE t; +# End of 10.6 tests diff --git a/mysql-test/main/mdev-37000.test b/mysql-test/main/mdev-37000.test new file mode 100644 index 00000000000..631be073f8c --- /dev/null +++ b/mysql-test/main/mdev-37000.test @@ -0,0 +1,9 @@ +--echo # +--echo # MDEV-37000 Deleting a row from Aria table results to 'Index is corrupt' +--echo # +CREATE OR REPLACE TABLE t (a INT, b CHAR(8) NOT NULL, KEY(b)) ENGINE=Aria DEFAULT CHARSET=utf8; +INSERT INTO t VALUES (1,'20070101'), (2,'20070101'); +DELETE FROM t LIMIT 2; +DROP TABLE t; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index c8c53c9036a..25a72885317 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -245,6 +245,14 @@ DECLARE a mysql_json; END; $$ ERROR HY000: 'MYSQL_JSON' is not allowed in this context -# # End of 10.5 tests # +# MDEV-40678 mysql_json plugin OOB reads +# +alter table t1 force; +ERROR HY000: Error parsing MySQL JSON format, please dump this table from MySQL and then restore it to be able to use it in MariaDB. +flush tables; +alter table t1 force; +ERROR HY000: Error parsing MySQL JSON format, please dump this table from MySQL and then restore it to be able to use it in MariaDB. +drop table t1; +# End of 10.6 tests diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index 94477d4f328..26cc7a6cc6b 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -17,7 +17,7 @@ call mtr.add_suppression("Table rebuild required"); call mtr.add_suppression("is marked as crashed"); call mtr.add_suppression("Checking"); -let $MYSQLD_DATADIR= `select @@datadir`; +let MYSQLD_DATADIR= `select @@datadir`; SET NAMES utf8; @@ -161,6 +161,40 @@ END; $$ DELIMITER ;$$ ---echo # --echo # End of 10.5 tests + --echo # +--echo # MDEV-40678 mysql_json plugin OOB reads +--echo # + +--copy_file std_data/mysql_json/mysql_json_test.frm $MYSQLD_DATADIR/test/t1.frm +--copy_file std_data/mysql_json/mysql_json_test.MYI $MYSQLD_DATADIR/test/t1.MYI +--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/test/t1.MYD + +perl; + my $f="$ENV{MYSQLD_DATADIR}/test/t1.MYD"; + open F, '+<', $f or die "open($f): $!"; + sysseek F, 0x3c5, 0 or die "sysseek: $!"; + syswrite F, '(' or die "syswrite: $!"; +EOF + +--error ER_UNKNOWN_ERROR +alter table t1 force; +flush tables; + +--remove_file $MYSQLD_DATADIR/test/t1.MYD +--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/test/t1.MYD + +perl; + my $f="$ENV{MYSQLD_DATADIR}/test/t1.MYD"; + open F, '+<', $f or die "open($f): $!"; + sysseek F, 0x3bc, 0 or die "sysseek: $!"; + syswrite F, '(' or die "syswrite: $!"; +EOF + +--error ER_UNKNOWN_ERROR +alter table t1 force; + +drop table t1; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/mysqld--help,win.rdiff b/mysql-test/main/mysqld--help,win.rdiff index 6016db9eac9..67f2651bdc8 100644 --- a/mysql-test/main/mysqld--help,win.rdiff +++ b/mysql-test/main/mysqld--help,win.rdiff @@ -16,7 +16,17 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -1374,6 +1376,10 @@ +@@ -1216,8 +1218,7 @@ + (Defaults to on; use --skip-secure-auth to disable.) + --secure-file-priv=name + Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to +- files within specified directory. Empty value means no +- limits except /proc ++ files within specified directory. + --secure-timestamp=name + Restricts direct setting of a session timestamp. Possible + levels are: YES - timestamp cannot deviate from the +@@ -1375,6 +1376,10 @@ Alias for log_slow_query_file. Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -27,7 +37,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1394,6 +1400,7 @@ +@@ -1395,6 +1400,7 @@ aborted. Prevents the common mistake of accidentally deleting or updating every row in a table. --stack-trace Print a symbolic stack trace on failure @@ -35,7 +45,7 @@ --standard-compliant-cte Allow only CTEs compliant to SQL standard (Defaults to on; use --skip-standard-compliant-cte to disable.) -@@ -1472,6 +1479,12 @@ +@@ -1473,6 +1479,12 @@ --thread-pool-max-threads=# Maximum allowed number of worker threads in the thread pool @@ -48,7 +58,7 @@ --thread-pool-oversubscribe=# How many additional active worker threads in a group are allowed. -@@ -1510,8 +1523,8 @@ +@@ -1511,8 +1523,8 @@ automatically convert it to an on-disk MyISAM or Aria table. -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -59,7 +69,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1731,6 +1744,7 @@ +@@ -1732,6 +1744,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -67,7 +77,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1891,6 +1905,7 @@ +@@ -1892,6 +1905,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -75,7 +85,7 @@ sort-buffer-size 2097152 sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION sql-safe-updates FALSE -@@ -1917,6 +1932,8 @@ +@@ -1918,6 +1932,8 @@ thread-pool-exact-stats FALSE thread-pool-idle-timeout 60 thread-pool-max-threads 65536 diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 1e80bede89b..883c3eecadf 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1216,7 +1216,8 @@ The following specify which files/extra groups are read (specified before remain (Defaults to on; use --skip-secure-auth to disable.) --secure-file-priv=name Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to - files within specified directory + files within specified directory. Empty value means no + limits except /proc --secure-timestamp=name Restricts direct setting of a session timestamp. Possible levels are: YES - timestamp cannot deviate from the diff --git a/mysql-test/main/mysqltest.result b/mysql-test/main/mysqltest.result index af12773b193..747d6f2e706 100644 --- a/mysql-test/main/mysqltest.result +++ b/mysql-test/main/mysqltest.result @@ -1023,6 +1023,12 @@ the false block has written nothing mysqltest: At line 1: End of file encountered before 'eval' delimiter was found # Only 'eval' is allowed as the third argument mysqltest: At line 1: Invalid argument 'junk' to 'write_file', only 'eval' is allowed +# +# \0 in a query +# +select hex("12"); +hex("1\x002") +310032 # End of 10.6 tests # # MDEV-29344: engines/iuds.insert_time cannot run with PS protocol (syntax error) diff --git a/mysql-test/main/mysqltest.test b/mysql-test/main/mysqltest.test index f4061c09045..8932b061c57 100644 --- a/mysql-test/main/mysqltest.test +++ b/mysql-test/main/mysqltest.test @@ -3054,6 +3054,11 @@ EOF --error 1 --exec echo "--write_file $file EOF junk" | $MYSQL_TEST 2>&1 +--echo # +--echo # \0 in a query +--echo # +select hex("12"); + --echo # End of 10.6 tests --echo # @@ -3077,12 +3082,11 @@ SELECT 1 /* doesn't throw error */; --rmdir $srcdir +--echo # End of 10.11 tests + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc --disable_query_log --eval SET GLOBAL max_connections = $saved_max_connections --enable_query_log - ---echo # End of 10.11 tests - diff --git a/mysql-test/main/mysqltest_expression_evaluation.result b/mysql-test/main/mysqltest_expression_evaluation.result index d9fa0ccb3b8..b74fc767d47 100644 --- a/mysql-test/main/mysqltest_expression_evaluation.result +++ b/mysql-test/main/mysqltest_expression_evaluation.result @@ -505,4 +505,11 @@ mysqltest: At line 1: Evaluation error: Modulo by zero # Test case: Overflow mysqltest: At line 1: Range error: 18446744073709551616 value out of range for Integer type mysqltest: At line 1: Range error: 18446744073709551616 value out of range for Integer type +# +# MDEV-37865: IF() function is returning incorrect error +# +# Test case: unknown function name that is a prefix of a known one +mysqltest: At line 1: Syntax error: Unknown function 'if' +mysqltest: At line 1: Syntax error: Unknown function 'l' # Expression evaluation tests completed successfully +# End of 10.6 tests diff --git a/mysql-test/main/mysqltest_expression_evaluation.test b/mysql-test/main/mysqltest_expression_evaluation.test index 7a108f2fe17..b76648284fc 100644 --- a/mysql-test/main/mysqltest_expression_evaluation.test +++ b/mysql-test/main/mysqltest_expression_evaluation.test @@ -894,4 +894,17 @@ let $large_xor = $(0x7FFFFFFFFFFFFFFF ^ 0x7FFFFFFFFFFFFFFE); --error 1 --exec echo "let \$a = \$(-18446744073709551616);" | $MYSQL_TEST 2>&1 +--echo # +--echo # MDEV-37865: IF() function is returning incorrect error +--echo # + +--echo # Test case: unknown function name that is a prefix of a known one +--error 1 +--exec echo "let \$a = \$(if(null, 'fallback', 'actual'));" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let \$a = \$(l('AB'));" | $MYSQL_TEST 2>&1 + --echo # Expression evaluation tests completed successfully + +--echo # End of 10.6 tests diff --git a/mysql-test/main/mysqltest_string_functions.result b/mysql-test/main/mysqltest_string_functions.result index eb3d56e6554..2f4eb0c94b0 100644 --- a/mysql-test/main/mysqltest_string_functions.result +++ b/mysql-test/main/mysqltest_string_functions.result @@ -1116,4 +1116,11 @@ insert(upper('hello world'), 7, 5, lower('MARIADB')) -> HELLO mariadb concat_ws(' ', upper('hello'), lower('WORLD')) -> HELLO world ifnull(nullif('same', 'same'), 'default') -> default coalesce(nullif('test', 'test'), 'backup') -> backup +# +# MDEV-37859: Mysqltest hex() not working for string values +# +hex("abc") -> 616263 +hex("255") -> 323535 +hex('') -> # Expression evaluation string functions tests completed successfully +# End of 10.6 tests diff --git a/mysql-test/main/mysqltest_string_functions.test b/mysql-test/main/mysqltest_string_functions.test index 10e0d546e15..4ccdfec59c0 100644 --- a/mysql-test/main/mysqltest_string_functions.test +++ b/mysql-test/main/mysqltest_string_functions.test @@ -2128,4 +2128,19 @@ let $result5 = $(ifnull(nullif('same', 'same'), 'default')); let $result6 = $(coalesce(nullif('test', 'test'), 'backup')); --echo coalesce(nullif('test', 'test'), 'backup') -> $result6 +--echo # +--echo # MDEV-37859: Mysqltest hex() not working for string values +--echo # + +let $hex_str1 = $(hex("abc")); +--echo hex("abc") -> $hex_str1 + +let $hex_str2 = $(hex("255")); +--echo hex("255") -> $hex_str2 + +let $hex_str3 = $(hex('')); +--echo hex('') -> $hex_str3 + --echo # Expression evaluation string functions tests completed successfully + +--echo # End of 10.6 tests diff --git a/mysql-test/main/rli_run_lock.result b/mysql-test/main/rli_run_lock.result new file mode 100644 index 00000000000..e2776a356d0 --- /dev/null +++ b/mysql-test/main/rli_run_lock.result @@ -0,0 +1,18 @@ +CHANGE MASTER TO master_host='127.0.0.1', master_user='root'; +START SLAVE SQL_THREAD; +include/wait_for_slave_sql_to_start.inc +SET @@SESSION.debug_sync= +'hold_sss_with_run_lock SIGNAL sss_got_run_lock WAIT_FOR sss_continue'; +SHOW SLAVE STATUS; +connect stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1; +SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock'; +STOP SLAVE SQL_THREAD; +connect continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1; +SET @@SESSION.debug_sync= 'now SIGNAL sss_continue'; +connection stopper; +disconnect continuer; +connection default; +disconnect stopper; +SET @@SESSION.debug_sync= RESET; +include/wait_for_slave_sql_to_stop.inc +RESET SLAVE ALL; diff --git a/mysql-test/main/rli_run_lock.test b/mysql-test/main/rli_run_lock.test new file mode 100644 index 00000000000..ca8eaf4d929 --- /dev/null +++ b/mysql-test/main/rli_run_lock.test @@ -0,0 +1,43 @@ +# MDEV-40298 +# Use-After-Free when SQL Thread stops in the middle of SHOW SLAVE STATUS +# +# Test that the correct synchronization is performed + +--source include/have_debug_sync.inc +--source include/have_binlog_format_mixed.inc # No actual replication required +CHANGE MASTER TO master_host='127.0.0.1', master_user='root'; # basic setup + +START SLAVE SQL_THREAD; +--source include/wait_for_slave_sql_to_start.inc + + +SET @@SESSION.debug_sync= + 'hold_sss_with_run_lock SIGNAL sss_got_run_lock WAIT_FOR sss_continue'; +--send SHOW SLAVE STATUS + +--connect (stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1) + SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock'; + --send STOP SLAVE SQL_THREAD + # Wait a bit for the thread to "shut down" + # (It should not shut down, but block waiting for the ongoing SSS; + # the tested bug instead pulled this carpet under the SSS's feet.) + --sleep 1 + + --connect (continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1) + SET @@SESSION.debug_sync= 'now SIGNAL sss_continue'; + --connection stopper + --disconnect continuer + + --reap +--connection default +--disconnect stopper + + +--disable_result_log + --reap +--enable_result_log + +# Clean-up +SET @@SESSION.debug_sync= RESET; +--source include/wait_for_slave_sql_to_stop.inc +RESET SLAVE ALL; diff --git a/mysql-test/main/xml.result b/mysql-test/main/xml.result index 1cf232e5475..e699a8fb108 100644 --- a/mysql-test/main/xml.result +++ b/mysql-test/main/xml.result @@ -1414,11 +1414,4 @@ ExtractValue(@xml, '/employee/dt3') NULL Warnings: Warning 1525 Incorrect XML value: 'parse error at line 10 pos 27: unexpected END-OF-INPUT' -# -# MDEV-39750 ExtractValue does not control recursion depth. -# -SELECT ExtractValue('', REPEAT('(', 100000)); -ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. -SELECT ExtractValue('', REPEAT('/n', 100000)); -ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. # End of 10.6 tests diff --git a/mysql-test/main/xml.test b/mysql-test/main/xml.test index f849e81d974..bc1e36a0eb8 100644 --- a/mysql-test/main/xml.test +++ b/mysql-test/main/xml.test @@ -899,17 +899,5 @@ set @xml= ' SELECT ExtractValue(@xml, '/employee/dt3'); ---echo # ---echo # MDEV-39750 ExtractValue does not control recursion depth. ---echo # - ---replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/ ---error ER_STACK_OVERRUN_NEED_MORE -SELECT ExtractValue('', REPEAT('(', 100000)); - ---replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/ ---error ER_STACK_OVERRUN_NEED_MORE -SELECT ExtractValue('', REPEAT('/n', 100000)); - --echo # End of 10.6 tests diff --git a/mysql-test/suite/archive/repair_text.result b/mysql-test/suite/archive/repair_text.result new file mode 100644 index 00000000000..67926d923cf --- /dev/null +++ b/mysql-test/suite/archive/repair_text.result @@ -0,0 +1,12 @@ +CREATE TABLE t1( +t TEXT NULL DEFAULT NULL +) COLLATE='utf8_general_ci' ENGINE=archive; +INSERT INTO t1(t) VALUES ('Testtext'); +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT t = 'Testtext' as Expect_1 from t1; +Expect_1 +1 +DROP TABLE t1; +# End of 10.6 tests diff --git a/mysql-test/suite/archive/repair_text.test b/mysql-test/suite/archive/repair_text.test new file mode 100644 index 00000000000..842b1edb201 --- /dev/null +++ b/mysql-test/suite/archive/repair_text.test @@ -0,0 +1,10 @@ +--source include/have_archive.inc +CREATE TABLE t1( + t TEXT NULL DEFAULT NULL +) COLLATE='utf8_general_ci' ENGINE=archive; +INSERT INTO t1(t) VALUES ('Testtext'); +REPAIR TABLE t1; +SELECT t = 'Testtext' as Expect_1 from t1; +DROP TABLE t1; + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/compat/oracle/r/sp-package-security.result b/mysql-test/suite/compat/oracle/r/sp-package-security.result index c08b78cb8cf..c11589a0ea4 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package-security.result +++ b/mysql-test/suite/compat/oracle/r/sp-package-security.result @@ -320,3 +320,26 @@ SESSION_USER() CURRENT_USER() msg root@localhost root@localhost p1.p1 DROP PACKAGE p1; DROP USER xxx@localhost; +# +# MDEV-40722 DROP PACKAGE leaves PACKAGE BODY grant in mysql.procs_priv +# +CREATE PACKAGE pkg1 AS +FUNCTION f RETURN VARCHAR2(64); +END +$$ +CREATE PACKAGE BODY pkg1 AS +FUNCTION f RETURN VARCHAR2(64) AS +BEGIN RETURN 'f'; +END; +END$$ +CREATE USER reader@localhost; +GRANT EXECUTE ON PACKAGE test.pkg1 TO reader@localhost; +GRANT EXECUTE ON PACKAGE BODY test.pkg1 TO reader@localhost; +SELECT host,db,user,routine_name,routine_type,proc_priv FROM mysql.procs_priv ORDER BY routine_type; +host db user routine_name routine_type proc_priv +localhost test reader pkg1 PACKAGE Execute +localhost test reader pkg1 PACKAGE BODY Execute +DROP PACKAGE pkg1; +SELECT host,db,user,routine_name,routine_type,proc_priv FROM mysql.procs_priv ORDER BY routine_type; +host db user routine_name routine_type proc_priv +DROP USER reader@localhost; diff --git a/mysql-test/suite/compat/oracle/t/sp-package-security.test b/mysql-test/suite/compat/oracle/t/sp-package-security.test index 583f70afe14..20a4fddb5b4 100644 --- a/mysql-test/suite/compat/oracle/t/sp-package-security.test +++ b/mysql-test/suite/compat/oracle/t/sp-package-security.test @@ -330,3 +330,28 @@ DELIMITER ;$$ CALL p1.p1; DROP PACKAGE p1; DROP USER xxx@localhost; + + +--echo # +--echo # MDEV-40722 DROP PACKAGE leaves PACKAGE BODY grant in mysql.procs_priv +--echo # + +DELIMITER $$; +CREATE PACKAGE pkg1 AS + FUNCTION f RETURN VARCHAR2(64); +END +$$ +CREATE PACKAGE BODY pkg1 AS + FUNCTION f RETURN VARCHAR2(64) AS + BEGIN RETURN 'f'; + END; +END$$ +DELIMITER ;$$ + +CREATE USER reader@localhost; +GRANT EXECUTE ON PACKAGE test.pkg1 TO reader@localhost; +GRANT EXECUTE ON PACKAGE BODY test.pkg1 TO reader@localhost; +SELECT host,db,user,routine_name,routine_type,proc_priv FROM mysql.procs_priv ORDER BY routine_type; +DROP PACKAGE pkg1; +SELECT host,db,user,routine_name,routine_type,proc_priv FROM mysql.procs_priv ORDER BY routine_type; +DROP USER reader@localhost; diff --git a/mysql-test/suite/csv/delete.result b/mysql-test/suite/csv/delete.result new file mode 100644 index 00000000000..73dc585fc26 --- /dev/null +++ b/mysql-test/suite/csv/delete.result @@ -0,0 +1,11 @@ +# +# MDEV-40636 CSV crashes on DELETE +# +create table t1 (id int not null, pad char(10) not null) engine=csv; +insert t1 select seq,'AAAAAAAAAA' from seq_1_to_2048; +delete from t1 where id % 2 = 0; +select count(*), sum(id) from t1; +count(*) sum(id) +1024 1048576 +drop table t1; +# End of 10.6 tests diff --git a/mysql-test/suite/csv/delete.test b/mysql-test/suite/csv/delete.test new file mode 100644 index 00000000000..2b4b1eea6c9 --- /dev/null +++ b/mysql-test/suite/csv/delete.test @@ -0,0 +1,13 @@ +--source include/have_csv.inc +--source include/have_sequence.inc + +--echo # +--echo # MDEV-40636 CSV crashes on DELETE +--echo # +create table t1 (id int not null, pad char(10) not null) engine=csv; +insert t1 select seq,'AAAAAAAAAA' from seq_1_to_2048; +delete from t1 where id % 2 = 0; +select count(*), sum(id) from t1; +drop table t1; + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/encryption/r/filekeys_encfile_badfile.result b/mysql-test/suite/encryption/r/filekeys_encfile_badfile.result index 7e244c2c381..5dcf1857c44 100644 --- a/mysql-test/suite/encryption/r/filekeys_encfile_badfile.result +++ b/mysql-test/suite/encryption/r/filekeys_encfile_badfile.result @@ -1,9 +1,46 @@ -call mtr.add_suppression("File 'bad' not found"); +call mtr.add_suppression("File 'bad.key' not found"); call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); -FOUND 1 /File 'bad' not found/ in mysqld.1.err +FOUND 1 /File 'bad.key' not found/ in mysqld.1.err create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") select plugin_status from information_schema.plugins where plugin_name = 'file_key_management'; plugin_status +install soname 'file_key_management'; +ERROR HY000: Cannot decrypt MTR_SUITE_DIR/t/filekeys-data.enc. Wrong key? +call mtr.add_suppression("Cannot decrypt .*filekeys-data.enc. Wrong key"); +call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); +call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); +FOUND 1 /Cannot decrypt .*filekeys-data.enc. Wrong key/ in mysqld.1.err +create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +select plugin_status from information_schema.plugins +where plugin_name = 'file_key_management'; +plugin_status +install soname 'file_key_management'; +ERROR HY000: Cannot read bad.key, the filekey is too long, max secret size is 256B +call mtr.add_suppression("the filekey is too long"); +call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); +call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); +FOUND 1 /the filekey is too long/ in mysqld.1.err +create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +select plugin_status from information_schema.plugins +where plugin_name = 'file_key_management'; +plugin_status +# +# MDEV-40658 file_key_management crash on empty FILE: file +# +install soname 'file_key_management'; +ERROR HY000: Cannot decrypt MTR_SUITE_DIR/t/filekeys-data.enc. Wrong key? +call mtr.add_suppression("Cannot decrypt .*filekeys-data.enc. Wrong key"); +call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); +call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); +FOUND 1 /Cannot decrypt .*filekeys-data.enc. Wrong key/ in mysqld.1.err +create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +select plugin_status from information_schema.plugins +where plugin_name = 'file_key_management'; +plugin_status +# End of 10.6 tests diff --git a/mysql-test/suite/encryption/r/filekeys_secret_too_long.result b/mysql-test/suite/encryption/r/filekeys_secret_too_long.result deleted file mode 100644 index bd11e8d925e..00000000000 --- a/mysql-test/suite/encryption/r/filekeys_secret_too_long.result +++ /dev/null @@ -1,10 +0,0 @@ -call mtr.add_suppression("the filekey is too long"); -call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); -call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); -FOUND 1 /the filekey is too long/ in mysqld.1.err -create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -select plugin_status from information_schema.plugins -where plugin_name = 'file_key_management'; -plugin_status -# Test checks if opening an too large secret does not crash the server. diff --git a/mysql-test/suite/encryption/t/filekeys-data-too-long.key b/mysql-test/suite/encryption/t/filekeys-data-too-long.key deleted file mode 100644 index ba1624fb324..00000000000 --- a/mysql-test/suite/encryption/t/filekeys-data-too-long.key +++ /dev/null @@ -1,4 +0,0 @@ -secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret -secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret -secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret - diff --git a/mysql-test/suite/encryption/t/filekeys_encfile_badfile.opt b/mysql-test/suite/encryption/t/filekeys_encfile_badfile.opt index 374a41395b8..713ce507eac 100644 --- a/mysql-test/suite/encryption/t/filekeys_encfile_badfile.opt +++ b/mysql-test/suite/encryption/t/filekeys_encfile_badfile.opt @@ -1,2 +1,2 @@ ---loose-file-key-management-filekey=FILE:bad +--loose-file-key-management-filekey=FILE:bad.key --loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data.enc diff --git a/mysql-test/suite/encryption/t/filekeys_encfile_badfile.test b/mysql-test/suite/encryption/t/filekeys_encfile_badfile.test index e0b07ac62b1..6af2e1c2f01 100644 --- a/mysql-test/suite/encryption/t/filekeys_encfile_badfile.test +++ b/mysql-test/suite/encryption/t/filekeys_encfile_badfile.test @@ -1,2 +1,51 @@ -let SEARCH_PATTERN=File 'bad' not found; -source filekeys_badtest.inc; +# +# first test: no file +# +--let SEARCH_PATTERN=File 'bad.key' not found +--source filekeys_badtest.inc + +# +# second test: wrong key +# +--let $datadir=`select @@datadir` +--write_file $datadir/bad.key +wrong key +EOF +--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR +--error 2 +install soname 'file_key_management'; +--let SEARCH_PATTERN=Cannot decrypt .*filekeys-data.enc. Wrong key +--source filekeys_badtest.inc +--remove_file $datadir/bad.key + +# +# third test: too long key +# +--let $datadir=`select @@datadir` +--write_file $datadir/bad.key +secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret +secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret +secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret +EOF +--error 2 +install soname 'file_key_management'; +--let SEARCH_PATTERN=the filekey is too long +--source filekeys_badtest.inc +--remove_file $datadir/bad.key + +--echo # +--echo # MDEV-40658 file_key_management crash on empty FILE: file +--echo # +--let $datadir=`select @@datadir` +--write_file $datadir/bad.key + + +EOF +--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR +--error 2 +install soname 'file_key_management'; +--let SEARCH_PATTERN=Cannot decrypt .*filekeys-data.enc. Wrong key +--source filekeys_badtest.inc +--remove_file $datadir/bad.key + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/encryption/t/filekeys_secret_too_long.opt b/mysql-test/suite/encryption/t/filekeys_secret_too_long.opt deleted file mode 100644 index c3f95019f2a..00000000000 --- a/mysql-test/suite/encryption/t/filekeys_secret_too_long.opt +++ /dev/null @@ -1,3 +0,0 @@ ---loose-file-key-management-filekey=FILE:$MTR_SUITE_DIR/t/filekeys-data-too-long.key ---loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data.enc - diff --git a/mysql-test/suite/encryption/t/filekeys_secret_too_long.test b/mysql-test/suite/encryption/t/filekeys_secret_too_long.test deleted file mode 100644 index 0032e94de37..00000000000 --- a/mysql-test/suite/encryption/t/filekeys_secret_too_long.test +++ /dev/null @@ -1,4 +0,0 @@ -let SEARCH_PATTERN=the filekey is too long; -source filekeys_badtest.inc; - ---echo # Test checks if opening an too large secret does not crash the server. diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index f0996fa3a97..391cdbf6019 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -34,6 +34,8 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf index 43bd091c8ee..64f10b086e1 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf @@ -48,6 +48,8 @@ wsrep-on=OFF server-id=3 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf b/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf index 570eeda0bc6..32f02ad0876 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf @@ -54,6 +54,8 @@ gtid_domain_id=4 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf index c00e6c6a937..75c247d05b3 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -47,6 +47,8 @@ wsrep-on=OFF server-id=3 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_2x2nodes.cnf b/mysql-test/suite/galera/galera_2x2nodes.cnf index a35baed0c32..68d81983528 100644 --- a/mysql-test/suite/galera/galera_2x2nodes.cnf +++ b/mysql-test/suite/galera/galera_2x2nodes.cnf @@ -61,6 +61,8 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf index 6231da6c246..b1091cfd645 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -60,6 +60,8 @@ wsrep-on=OFF server-id=4 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf index 3006882eda3..c54ff58e5e2 100644 --- a/mysql-test/suite/galera/galera_4nodes.cnf +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -61,6 +61,8 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' auto-increment-offset=4 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera/include/have_pkill.inc b/mysql-test/suite/galera/include/have_pkill.inc new file mode 100644 index 00000000000..0dd693f2c63 --- /dev/null +++ b/mysql-test/suite/galera/include/have_pkill.inc @@ -0,0 +1,4 @@ +# +# suite.pm will make sure that all tests including this file +# will be skipped as needed +# diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_missing_ssl.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_missing_ssl.result new file mode 100644 index 00000000000..0424988061e --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_missing_ssl.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +connection node_2; +# Force a fresh SST on node_2 +# Start node_2 with SSL cert/key simulated as missing +# node_2 failed to start, as expected +# Joiner refused the SST instead of running unencrypted +FOUND 1 /ssl-mode is set to .REQUIRED., but no usable SSL/ in mysqld.2.err +# Restart node_2 normally so it rejoins +connection node_2; +call mtr.add_suppression("WSREP_SST:"); +call mtr.add_suppression("WSREP: Process completed with error:"); +call mtr.add_suppression("WSREP: Failed to read .ready ."); +call mtr.add_suppression("WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script."); +call mtr.add_suppression("WSREP: Failed to read state from: .*"); +call mtr.add_suppression("WSREP: Failed to prepare for .*"); +call mtr.add_suppression("WSREP: SST failed:.*"); +call mtr.add_suppression("WSREP: SST request callback failed. This is unrecoverable, restart required."); +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +call mtr.add_suppression("WSREP: Requesting state transfer failed:.*"); +connection node_1; diff --git a/mysql-test/suite/galera/r/galera_sst_rsync_missing_stunnel.result b/mysql-test/suite/galera/r/galera_sst_rsync_missing_stunnel.result new file mode 100644 index 00000000000..771d6e0fd75 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_rsync_missing_stunnel.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +connection node_2; +# Force a fresh SST on node_2 +# Start node_2 with stunnel simulated as missing +# node_2 failed to start, as expected +# Joiner refused the SST instead of running unencrypted +FOUND 1 /ssl-mode is set to .REQUIRED., but the .stunnel. binary was not found/ in mysqld.2.err +# Restart node_2 normally so it rejoins +connection node_2; +call mtr.add_suppression("WSREP_SST:"); +call mtr.add_suppression("WSREP: Process completed with error:"); +call mtr.add_suppression("WSREP: Failed to read .ready ."); +call mtr.add_suppression("WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script."); +call mtr.add_suppression("WSREP: Failed to read state from: .*"); +call mtr.add_suppression("WSREP: Failed to prepare for .*"); +call mtr.add_suppression("WSREP: SST failed:.*"); +call mtr.add_suppression("WSREP: SST request callback failed. This is unrecoverable, restart required."); +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +call mtr.add_suppression("WSREP: Requesting state transfer failed:.*"); +connection node_1; diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 612a8bfa595..b4fd4c62f06 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -80,6 +80,10 @@ sub skip_combinations { unless which("lsof") || which("sockstat") || which("ss"); $skip{'include/have_stunnel.inc'} = "Need 'stunnel' utility" unless which("stunnel"); + # 'mariabackup' combination doesn't need stunnel: only 'rsync' SST goes + # through it. + $skip{'t/galera_sst_cn_injection.combinations'} = [ 'rsync' ] + unless which("stunnel"); $skip{'include/have_qpress.inc'} = "Need 'qpress' utility" unless which("qpress"); $skip{'../encryption/include/have_file_key_management_plugin.combinations'} = [ 'ctr' ] @@ -93,6 +97,9 @@ sub skip_combinations { $skip{'t/galera_sst_cn_injection.test'} = 'does not work with OpenSSL <= 1.1.1' unless $openssl_ver ge "3.0.0"; + $skip{'include/have_pkill.inc'} = "Need 'pkill' utility" + unless which("pkill"); + %skip; } diff --git a/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test index d9f7bb152fc..fb16ba7f8d3 100644 --- a/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test +++ b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test @@ -1,6 +1,7 @@ --source include/big_test.inc --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/have_stunnel.inc --let $node_1=node_1 --let $node_2=node_2 diff --git a/mysql-test/suite/galera/t/galera_sst_cn_injection.test b/mysql-test/suite/galera/t/galera_sst_cn_injection.test index 9b8058267e8..b970950a0a5 100644 --- a/mysql-test/suite/galera/t/galera_sst_cn_injection.test +++ b/mysql-test/suite/galera/t/galera_sst_cn_injection.test @@ -10,6 +10,7 @@ --source include/have_mariabackup.inc --source include/have_ssl_communication.inc --source include/have_openssl.inc +--source include/have_pkill.inc # This test asserts that the initial cluster-bootstrap SST was SSL-encrypted by # grepping the donor's error log. That is a one-time event, so the cluster must # be freshly bootstrapped on every run (e.g. with --repeat) for node_2 to SST @@ -56,7 +57,8 @@ call mtr.add_suppression("WSREP: Illegal character in variable:"); --echo # cleanup # we have to kill joiner's socat here, because the donor has aborted SST # and joiner's socat will timeout in 5 minutes -# pkill exit code varies by platform 0 or 1 +# pkill below might return 0 = success or 1 in error when it does not find socat +# anymore --error 0,1,15 --exec pkill -f 'socat.*[s]erver-new-cert' --exec echo ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem >> $MYSQLTEST_VARDIR/my.cnf diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.cnf new file mode 100644 index 00000000000..5c9ea2149a3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth="root:" +ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem +ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem +ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem + +[sst] +ssl-mode=REQUIRED diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.test new file mode 100644 index 00000000000..a636634cd50 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_missing_ssl.test @@ -0,0 +1,69 @@ +# MDEV-28233: with ssl-mode requiring encryption but no usable cert/key, +# wsrep_sst_mariabackup used to fall back to an unencrypted transfer +# WITHOUT any error or warning. Before the fix the joiner only logged the +# informational line: +# WSREP_SST: [INFO] SSL configuration: ... MODE='REQUIRED' ... encrypt='0' +# and then opened a cleartext socket. +# +# Steps: +# 1. Form a 2-node cluster with ssl-mode=REQUIRED and SSL cert/key. +# 2. Shut node_2 down and force a fresh SST. +# 3. Restart node_2 with cert/key simulated as missing +# (MTR_SST_SIMULATE_NO_SSL_CERT=1). +# 4. Check the joiner refuses the SST and logs the error. +# 5. Restart node_2 normally so it rejoins. +# +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +# Save auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--connection node_1 +# Donor-side noise when the joiner aborts the SST. +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); + +--connection node_2 +--source include/shutdown_mysqld.inc + +--echo # Force a fresh SST on node_2 +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + +--echo # Start node_2 with SSL cert/key simulated as missing +# Abort exit code varies by platform. +--error 1,134 +--exec MTR_SST_SIMULATE_NO_SSL_CERT=1 $MYSQLD_LAST_CMD +--echo # node_2 failed to start, as expected + +--echo # Joiner refused the SST instead of running unencrypted +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.2.err +--let SEARCH_PATTERN = ssl-mode is set to .REQUIRED., but no usable SSL +--source include/search_pattern_in_file.inc + +--echo # Restart node_2 normally so it rejoins +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +--connection node_2 +# Joiner-side noise from the failed SST attempt. +call mtr.add_suppression("WSREP_SST:"); +call mtr.add_suppression("WSREP: Process completed with error:"); +call mtr.add_suppression("WSREP: Failed to read .ready ."); +call mtr.add_suppression("WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script."); +call mtr.add_suppression("WSREP: Failed to read state from: .*"); +call mtr.add_suppression("WSREP: Failed to prepare for .*"); +call mtr.add_suppression("WSREP: SST failed:.*"); +call mtr.add_suppression("WSREP: SST request callback failed. This is unrecoverable, restart required."); +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +call mtr.add_suppression("WSREP: Requesting state transfer failed:.*"); + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.cnf b/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.cnf new file mode 100644 index 00000000000..39fbab6cb5c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.cnf @@ -0,0 +1,10 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync +ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem +ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem +ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem + +[sst] +ssl-mode=REQUIRED diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.test b/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.test new file mode 100644 index 00000000000..1310c27c6db --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_missing_stunnel.test @@ -0,0 +1,66 @@ +# MDEV-28233: the rsync SST script must NOT silently fall back to an +# unencrypted transfer when encryption is requested (ssl-mode is set to a +# value other than DISABLED) but the stunnel binary is not installed. +# +# Steps: +# 1. Form a 2-node cluster with ssl-mode=REQUIRED (stunnel present). +# 2. Shut node_2 down and force a fresh SST. +# 3. Restart node_2 with stunnel hidden (MTR_SST_SIMULATE_NO_STUNNEL=1). +# 4. Check the joiner refuses the SST and logs the error. +# 5. Restart node_2 normally so it rejoins. +# +--source include/galera_cluster.inc +--source include/have_innodb.inc +# Needed for the initial SST; only simulated as missing below. +--source include/have_stunnel.inc + +# Save auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--connection node_1 +# Donor-side noise when the joiner aborts the SST. +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); + +--connection node_2 +--source include/shutdown_mysqld.inc + +--echo # Force a fresh SST on node_2 +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + +--echo # Start node_2 with stunnel simulated as missing +# Abort exit code +--error 1,134 +--exec MTR_SST_SIMULATE_NO_STUNNEL=1 $MYSQLD_LAST_CMD +--echo # node_2 failed to start, as expected + +--echo # Joiner refused the SST instead of running unencrypted +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.2.err +--let SEARCH_PATTERN = ssl-mode is set to .REQUIRED., but the .stunnel. binary was not found +--source include/search_pattern_in_file.inc + +--echo # Restart node_2 normally so it rejoins +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +--connection node_2 +# Joiner-side noise from the failed SST attempt. +call mtr.add_suppression("WSREP_SST:"); +call mtr.add_suppression("WSREP: Process completed with error:"); +call mtr.add_suppression("WSREP: Failed to read .ready ."); +call mtr.add_suppression("WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script."); +call mtr.add_suppression("WSREP: Failed to read state from: .*"); +call mtr.add_suppression("WSREP: Failed to prepare for .*"); +call mtr.add_suppression("WSREP: SST failed:.*"); +call mtr.add_suppression("WSREP: SST request callback failed. This is unrecoverable, restart required."); +call mtr.add_suppression("WSREP: .*State transfer to.* failed:"); +call mtr.add_suppression("WSREP: Will never receive state. Need to abort."); +call mtr.add_suppression("WSREP: Requesting state transfer failed:.*"); + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf index 5cd16f029e0..b385d5c160f 100644 --- a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf @@ -85,6 +85,8 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.6.port wsrep_sst_receive_address='127.0.0.1:@mysqld.6.#sst_port' [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log [ENV] diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf index b0229971c57..35d51c98a0f 100644 --- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -50,6 +50,8 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' wsrep_node_name=node3 [sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log transferfmt=@ENV.MTR_GALERA_TFMT diff --git a/mysql-test/suite/plugins/r/qc_info.result b/mysql-test/suite/plugins/r/qc_info.result index afab7671b5c..5ad4e13f1e1 100644 Binary files a/mysql-test/suite/plugins/r/qc_info.result and b/mysql-test/suite/plugins/r/qc_info.result differ diff --git a/mysql-test/suite/plugins/t/qc_info.test b/mysql-test/suite/plugins/t/qc_info.test index 5345bac12ff..0bccd7f6672 100644 Binary files a/mysql-test/suite/plugins/t/qc_info.test and b/mysql-test/suite/plugins/t/qc_info.test differ diff --git a/mysql-test/suite/rpl/r/rpl_corrupted_decimal_precision.result b/mysql-test/suite/rpl/r/rpl_corrupted_decimal_precision.result index 9070bef9dc0..b56808e1128 100644 --- a/mysql-test/suite/rpl/r/rpl_corrupted_decimal_precision.result +++ b/mysql-test/suite/rpl/r/rpl_corrupted_decimal_precision.result @@ -27,7 +27,7 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test`; insert into t1 values (0.5) master-bin.000001 # Query # # COMMIT master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # User var # # +master-bin.000001 # User var # # NULL master-bin.000001 # Query # # use `test`; insert into t1 values (@a) master-bin.000001 # Query # # COMMIT set @@session.debug_dbug= ""; diff --git a/mysql-test/suite/sys_vars/r/secure_file_priv,win.rdiff b/mysql-test/suite/sys_vars/r/secure_file_priv,win.rdiff new file mode 100644 index 00000000000..44674696c9c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/secure_file_priv,win.rdiff @@ -0,0 +1,10 @@ +--- secure_file_priv.result ++++ secure_file_priv.reject +@@ -30,6 +30,6 @@ + # + CREATE TABLE t1 (c1 VARCHAR(50)); + LOAD DATA INFILE '/proc/cpuinfo' INTO TABLE t1; +-ERROR HY000: The MariaDB server is running with the --secure-file-priv option so it cannot execute this statement ++ERROR HY000: File 'C:\proc\cpuinfo' not found (Errcode: 2 "No such file or directory") + DROP TABLE t1; + # End of 10.6 tests diff --git a/mysql-test/suite/sys_vars/r/secure_file_priv.result b/mysql-test/suite/sys_vars/r/secure_file_priv.result index 74f816df59d..06968a185e7 100644 --- a/mysql-test/suite/sys_vars/r/secure_file_priv.result +++ b/mysql-test/suite/sys_vars/r/secure_file_priv.result @@ -6,14 +6,17 @@ INSERT INTO t1 VALUES ("one"),("two"),("three"),("four"),("five"); SHOW VARIABLES LIKE 'secure_file_priv'; Variable_name Value secure_file_priv -Warnings: -Warning 1287 ' INTO FROM...' instead +SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/../bug50373.txt' FROM t1; +DELETE FROM t1; +LOAD DATA INFILE '$MYSQLTEST_VARDIR/../bug50373.txt' INTO TABLE t1; +SELECT * FROM t1; c1 one two three four five +SELECT load_file('$MYSQLTEST_VARDIR/../bug50373.txt') AS loaded_file; loaded_file one two @@ -22,3 +25,11 @@ four five DROP TABLE t1; +# +# MDEV-40589 default exclude list for secure-file-priv +# +CREATE TABLE t1 (c1 VARCHAR(50)); +LOAD DATA INFILE '/proc/cpuinfo' INTO TABLE t1; +ERROR HY000: The MariaDB server is running with the --secure-file-priv option so it cannot execute this statement +DROP TABLE t1; +# End of 10.6 tests diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 15e9fc5089c..0d03c55b211 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -3175,7 +3175,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SECURE_FILE_PRIV VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory +VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory. Empty value means no limits except /proc NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff index acee8a39b43..77c7c9cf941 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff @@ -1,6 +1,6 @@ ---- suite/sys_vars/r/sysvars_server_notembedded.result -+++ suite/sys_vars/r/sysvars_server_notembedded.reject -@@ -34,7 +34,7 @@ +--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result ++++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +@@ -44,7 +44,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -9,7 +9,7 @@ VARIABLE_COMMENT Block size to be used for Aria index pages. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 32768 -@@ -44,7 +44,7 @@ +@@ -54,7 +54,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -18,7 +18,7 @@ VARIABLE_COMMENT Interval between tries to do an automatic checkpoints. In seconds; 0 means 'no automatic checkpoints' which makes sense only for testing. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -54,7 +54,7 @@ +@@ -64,7 +64,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_LOG_ACTIVITY VARIABLE_SCOPE GLOBAL @@ -27,7 +27,7 @@ VARIABLE_COMMENT Number of bytes that the transaction log has to grow between checkpoints before a new checkpoint is written to the log. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -74,7 +74,7 @@ +@@ -84,7 +84,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_FORCE_START_AFTER_RECOVERY_FAILURES VARIABLE_SCOPE GLOBAL @@ -36,7 +36,7 @@ VARIABLE_COMMENT Number of consecutive log recovery failures after which logs will be automatically deleted to cure the problem; 0 (the default) disables the feature. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -94,7 +94,7 @@ +@@ -104,7 +104,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -45,7 +45,7 @@ VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -114,7 +114,7 @@ +@@ -124,7 +124,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_LOG_FILE_SIZE VARIABLE_SCOPE GLOBAL @@ -54,7 +54,7 @@ VARIABLE_COMMENT Limit for transaction log size NUMERIC_MIN_VALUE 8388608 NUMERIC_MAX_VALUE 4294967295 -@@ -144,10 +144,10 @@ +@@ -154,10 +154,10 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_AGE_THRESHOLD VARIABLE_SCOPE GLOBAL @@ -67,7 +67,7 @@ NUMERIC_BLOCK_SIZE 100 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -164,7 +164,7 @@ +@@ -174,7 +174,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_DIVISION_LIMIT VARIABLE_SCOPE GLOBAL @@ -76,7 +76,7 @@ VARIABLE_COMMENT The minimum percentage of warm blocks in key cache NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100 -@@ -174,7 +174,7 @@ +@@ -184,7 +184,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_FILE_HASH_SIZE VARIABLE_SCOPE GLOBAL @@ -85,7 +85,7 @@ VARIABLE_COMMENT Number of hash buckets for open and changed files. If you have a lot of Aria files open you should increase this for faster flush of changes. A good value is probably 1/10 of number of possible open Aria files. NUMERIC_MIN_VALUE 128 NUMERIC_MAX_VALUE 16384 -@@ -204,7 +204,7 @@ +@@ -214,7 +214,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -94,7 +94,7 @@ VARIABLE_COMMENT Number of threads to use when repairing Aria tables. The value of 1 disables parallel repair. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -274,7 +274,7 @@ +@@ -284,7 +284,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_INCREMENT VARIABLE_SCOPE SESSION @@ -103,7 +103,7 @@ VARIABLE_COMMENT Auto-increment columns are incremented by this NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -284,7 +284,7 @@ +@@ -294,7 +294,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_OFFSET VARIABLE_SCOPE SESSION @@ -112,7 +112,7 @@ VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -294,7 +294,7 @@ +@@ -304,7 +304,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME BACK_LOG VARIABLE_SCOPE GLOBAL @@ -121,7 +121,7 @@ VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -364,20 +364,20 @@ +@@ -374,20 +374,20 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME BINLOG_COMMIT_WAIT_COUNT VARIABLE_SCOPE GLOBAL @@ -146,7 +146,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -394,7 +394,7 @@ +@@ -404,7 +404,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME BINLOG_EXPIRE_LOGS_SECONDS VARIABLE_SCOPE GLOBAL @@ -155,7 +155,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after binlog_expire_logs_seconds seconds; It and expire_logs_days are linked, such that changes in one are converted into the other. Possible purges happen at startup and at binary log rotation. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8553600 -@@ -654,7 +654,7 @@ +@@ -664,7 +664,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME CONNECT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -164,7 +164,7 @@ VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 31536000 -@@ -704,7 +704,7 @@ +@@ -714,7 +714,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_LONG VARIABLE_SCOPE SESSION @@ -173,7 +173,7 @@ VARIABLE_COMMENT Long search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 33 -@@ -714,7 +714,7 @@ +@@ -724,7 +724,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_SHORT VARIABLE_SCOPE SESSION @@ -182,7 +182,7 @@ VARIABLE_COMMENT Short search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 32 -@@ -724,7 +724,7 @@ +@@ -734,7 +734,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_LONG VARIABLE_SCOPE SESSION @@ -191,7 +191,7 @@ VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -734,7 +734,7 @@ +@@ -744,7 +744,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_SHORT VARIABLE_SCOPE SESSION @@ -200,7 +200,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -794,7 +794,7 @@ +@@ -804,7 +804,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_WEEK_FORMAT VARIABLE_SCOPE SESSION @@ -209,7 +209,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -804,7 +804,7 @@ +@@ -814,7 +814,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_LIMIT VARIABLE_SCOPE GLOBAL @@ -218,7 +218,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -814,7 +814,7 @@ +@@ -824,7 +824,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -227,7 +227,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -824,7 +824,7 @@ +@@ -834,7 +834,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_QUEUE_SIZE VARIABLE_SCOPE GLOBAL @@ -236,7 +236,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -854,7 +854,7 @@ +@@ -864,7 +864,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DIV_PRECISION_INCREMENT VARIABLE_SCOPE SESSION @@ -245,7 +245,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -974,7 +974,7 @@ +@@ -984,7 +984,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -254,7 +254,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -1004,7 +1004,7 @@ +@@ -1014,7 +1014,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME FLUSH_TIME VARIABLE_SCOPE GLOBAL @@ -263,7 +263,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1034,7 +1034,7 @@ +@@ -1044,7 +1044,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MAX_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -272,7 +272,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1044,7 +1044,7 @@ +@@ -1054,7 +1054,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MIN_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -281,7 +281,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -1054,7 +1054,7 @@ +@@ -1064,7 +1064,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT VARIABLE_SCOPE GLOBAL @@ -290,7 +290,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1304,7 +1304,7 @@ +@@ -1314,7 +1314,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HISTOGRAM_SIZE VARIABLE_SCOPE SESSION @@ -299,7 +299,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1334,7 +1334,7 @@ +@@ -1344,7 +1344,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HOST_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -308,7 +308,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1357,7 +1357,7 @@ +@@ -1367,7 +1367,7 @@ VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of seconds the server waits for read-only idle transaction NUMERIC_MIN_VALUE 0 @@ -317,7 +317,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1367,7 +1367,7 @@ +@@ -1377,7 +1377,7 @@ VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of seconds the server waits for idle transaction NUMERIC_MIN_VALUE 0 @@ -326,7 +326,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1377,7 +1377,7 @@ +@@ -1387,7 +1387,7 @@ VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of seconds the server waits for write idle transaction NUMERIC_MIN_VALUE 0 @@ -335,7 +335,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1444,7 +1444,7 @@ +@@ -1454,7 +1454,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME INTERACTIVE_TIMEOUT VARIABLE_SCOPE SESSION @@ -344,7 +344,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1494,7 +1494,7 @@ +@@ -1504,7 +1504,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME JOIN_CACHE_LEVEL VARIABLE_SCOPE SESSION @@ -353,7 +353,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1672,19 +1672,9 @@ +@@ -1682,19 +1682,9 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL @@ -374,7 +374,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1834,7 +1824,7 @@ +@@ -1844,7 +1834,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_MAX_WARNINGS VARIABLE_SCOPE SESSION @@ -383,7 +383,7 @@ VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1844,7 +1834,7 @@ +@@ -1854,7 +1844,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -392,7 +392,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1874,7 +1864,7 @@ +@@ -1884,7 +1874,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION @@ -401,7 +401,7 @@ VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1934,7 +1924,7 @@ +@@ -1944,7 +1934,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -410,7 +410,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1954,7 +1944,7 @@ +@@ -1964,7 +1954,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_SIZE VARIABLE_SCOPE GLOBAL @@ -419,7 +419,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1974,7 +1964,7 @@ +@@ -1984,7 +1974,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -428,7 +428,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -1984,7 +1974,7 @@ +@@ -1994,7 +1984,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -437,7 +437,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1994,7 +1984,7 @@ +@@ -2004,7 +1994,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -446,7 +446,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2014,7 +2004,7 @@ +@@ -2024,7 +2014,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -455,7 +455,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -2034,7 +2024,7 @@ +@@ -2044,7 +2034,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_INSERT_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -464,7 +464,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2054,7 +2044,7 @@ +@@ -2064,7 +2054,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -473,7 +473,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2084,7 +2074,7 @@ +@@ -2094,7 +2084,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -482,7 +482,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2114,7 +2104,7 @@ +@@ -2124,7 +2114,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SEEKS_FOR_KEY VARIABLE_SCOPE SESSION @@ -491,7 +491,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2134,7 +2124,7 @@ +@@ -2144,7 +2134,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION @@ -500,7 +500,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -2144,7 +2134,7 @@ +@@ -2154,7 +2144,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -509,7 +509,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2164,7 +2154,7 @@ +@@ -2174,7 +2164,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -518,7 +518,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2184,7 +2174,7 @@ +@@ -2194,7 +2184,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -527,7 +527,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2194,7 +2184,7 @@ +@@ -2204,7 +2194,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -536,7 +536,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2204,7 +2194,7 @@ +@@ -2214,7 +2204,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -545,7 +545,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2214,7 +2204,7 @@ +@@ -2224,7 +2214,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -554,7 +554,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2224,7 +2214,7 @@ +@@ -2234,7 +2224,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -563,7 +563,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2234,7 +2224,7 @@ +@@ -2244,7 +2234,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -572,7 +572,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2244,7 +2234,7 @@ +@@ -2254,7 +2244,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -581,7 +581,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2284,10 +2274,10 @@ +@@ -2294,10 +2284,10 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -594,7 +594,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2332,9 +2322,19 @@ +@@ -2342,9 +2332,19 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL @@ -615,7 +615,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2344,7 +2344,7 @@ +@@ -2354,7 +2354,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -624,7 +624,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2354,7 +2354,7 @@ +@@ -2364,7 +2364,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -633,7 +633,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2364,7 +2364,7 @@ +@@ -2374,7 +2374,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -642,7 +642,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2424,7 +2424,7 @@ +@@ -2434,7 +2434,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -651,16 +651,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2434,7 +2434,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED - VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS - VARIABLE_SCOPE SESSION --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 2 -@@ -2444,7 +2444,7 @@ +@@ -2464,7 +2464,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS VARIABLE_SCOPE SESSION @@ -669,7 +660,7 @@ VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2454,7 +2454,7 @@ +@@ -2474,7 +2474,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION @@ -678,7 +669,7 @@ VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2464,7 +2464,7 @@ +@@ -2484,7 +2484,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -687,7 +678,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2474,7 +2474,7 @@ +@@ -2494,7 +2494,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -696,7 +687,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2484,7 +2484,7 @@ +@@ -2504,7 +2504,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -705,7 +696,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2514,17 +2514,17 @@ +@@ -2534,17 +2534,17 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -726,7 +717,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2544,7 +2544,7 @@ +@@ -2564,7 +2564,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -735,7 +726,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2554,7 +2554,7 @@ +@@ -2574,7 +2574,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -744,7 +735,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2564,7 +2564,7 @@ +@@ -2584,7 +2584,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -753,7 +744,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2574,7 +2574,7 @@ +@@ -2594,7 +2594,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -762,7 +753,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2584,7 +2584,7 @@ +@@ -2604,7 +2604,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -771,7 +762,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2594,7 +2594,7 @@ +@@ -2614,7 +2614,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -780,7 +771,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2604,7 +2604,7 @@ +@@ -2624,7 +2624,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -789,7 +780,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2614,7 +2614,7 @@ +@@ -2634,7 +2634,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -798,7 +789,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2624,7 +2624,7 @@ +@@ -2644,7 +2644,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -807,7 +798,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2634,7 +2634,7 @@ +@@ -2654,7 +2654,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -816,7 +807,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2644,7 +2644,7 @@ +@@ -2664,7 +2664,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -825,7 +816,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2654,7 +2654,7 @@ +@@ -2674,7 +2674,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -834,7 +825,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2664,7 +2664,7 @@ +@@ -2684,7 +2684,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -843,7 +834,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2674,7 +2674,7 @@ +@@ -2694,7 +2694,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -852,7 +843,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2684,7 +2684,7 @@ +@@ -2704,7 +2704,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -861,7 +852,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2694,7 +2694,7 @@ +@@ -2714,7 +2714,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -870,7 +861,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2704,7 +2704,7 @@ +@@ -2724,7 +2724,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -879,7 +870,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2714,7 +2714,7 @@ +@@ -2734,7 +2734,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT VARIABLE_SCOPE GLOBAL @@ -888,7 +879,7 @@ VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2724,7 +2724,7 @@ +@@ -2744,7 +2744,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES VARIABLE_SCOPE GLOBAL @@ -897,7 +888,7 @@ VARIABLE_COMMENT Maximum number of memory pool instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2734,7 +2734,7 @@ +@@ -2754,7 +2754,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS VARIABLE_SCOPE GLOBAL @@ -906,7 +897,7 @@ VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2744,7 +2744,7 @@ +@@ -2764,7 +2764,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -915,7 +906,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2754,7 +2754,7 @@ +@@ -2774,7 +2774,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -924,7 +915,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2764,7 +2764,7 @@ +@@ -2784,7 +2784,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES VARIABLE_SCOPE GLOBAL @@ -933,7 +924,7 @@ VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2774,7 +2774,7 @@ +@@ -2794,7 +2794,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES VARIABLE_SCOPE GLOBAL @@ -942,7 +933,7 @@ VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2784,7 +2784,7 @@ +@@ -2804,7 +2804,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -951,7 +942,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2794,7 +2794,7 @@ +@@ -2814,7 +2814,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -960,7 +951,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2804,7 +2804,7 @@ +@@ -2824,7 +2824,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -969,7 +960,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2814,7 +2814,7 @@ +@@ -2834,7 +2834,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -978,7 +969,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2824,7 +2824,7 @@ +@@ -2844,7 +2844,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH VARIABLE_SCOPE GLOBAL @@ -987,7 +978,7 @@ VARIABLE_COMMENT Maximum length of displayed sql text. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2834,7 +2834,7 @@ +@@ -2854,7 +2854,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -996,7 +987,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2844,7 +2844,7 @@ +@@ -2864,7 +2864,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -1005,7 +996,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2854,7 +2854,7 @@ +@@ -2874,7 +2874,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK VARIABLE_SCOPE GLOBAL @@ -1014,7 +1005,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 256 -@@ -2864,7 +2864,7 @@ +@@ -2884,7 +2884,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -1023,7 +1014,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2874,7 +2874,7 @@ +@@ -2894,7 +2894,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1032,7 +1023,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2884,7 +2884,7 @@ +@@ -2904,7 +2904,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT VARIABLE_SCOPE GLOBAL @@ -1041,7 +1032,7 @@ VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2894,7 +2894,7 @@ +@@ -2914,7 +2914,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1050,7 +1041,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2904,7 +2904,7 @@ +@@ -2924,7 +2924,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1059,7 +1050,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2914,7 +2914,7 @@ +@@ -2934,7 +2934,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1068,7 +1059,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2924,7 +2924,7 @@ +@@ -2944,7 +2944,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1077,7 +1068,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2934,7 +2934,7 @@ +@@ -2954,7 +2954,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1086,7 +1077,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2944,7 +2944,7 @@ +@@ -2964,7 +2964,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1095,7 +1086,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2994,7 +2994,7 @@ +@@ -3014,7 +3014,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1104,7 +1095,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3014,7 +3014,7 @@ +@@ -3034,7 +3034,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1113,7 +1104,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3024,7 +3024,7 @@ +@@ -3044,7 +3044,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1122,7 +1113,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3084,7 +3084,7 @@ +@@ -3104,7 +3104,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1131,7 +1122,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3094,7 +3094,7 @@ +@@ -3114,7 +3114,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1140,7 +1131,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3104,7 +3104,7 @@ +@@ -3124,7 +3124,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1149,7 +1140,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3117,7 +3117,7 @@ +@@ -3137,7 +3137,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1158,7 +1149,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3154,7 +3154,7 @@ +@@ -3174,7 +3174,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1167,7 +1158,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3167,7 +3167,7 @@ +@@ -3187,7 +3187,7 @@ VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1176,7 +1167,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3177,14 +3177,14 @@ +@@ -3197,14 +3197,14 @@ VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1193,7 +1184,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3197,14 +3197,14 @@ +@@ -3217,14 +3217,14 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) NUMERIC_MIN_VALUE 0 @@ -1210,7 +1201,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3224,7 +3224,7 @@ +@@ -3244,7 +3244,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1219,7 +1210,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3434,10 +3434,10 @@ +@@ -3454,10 +3454,10 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1232,7 +1223,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3454,20 +3454,20 @@ +@@ -3474,20 +3474,20 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -1257,7 +1248,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3524,10 +3524,10 @@ +@@ -3544,10 +3544,10 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL VARIABLE_SCOPE GLOBAL @@ -1270,7 +1261,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3564,7 +3564,7 @@ +@@ -3565,7 +3565,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME SECURE_FILE_PRIV + VARIABLE_SCOPE GLOBAL + VARIABLE_TYPE VARCHAR +-VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory. Empty value means no limits except /proc ++VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory. + NUMERIC_MIN_VALUE NULL + NUMERIC_MAX_VALUE NULL + NUMERIC_BLOCK_SIZE NULL +@@ -3584,7 +3584,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1279,7 +1279,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3694,7 +3694,7 @@ +@@ -3724,7 +3724,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1288,7 +1288,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3724,7 +3724,7 @@ +@@ -3754,7 +3754,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1297,7 +1297,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3744,7 +3744,7 @@ +@@ -3774,7 +3774,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED VARIABLE_SCOPE GLOBAL @@ -1306,7 +1306,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3764,7 +3764,7 @@ +@@ -3794,7 +3794,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SLAVE_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1315,7 +1315,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3774,7 +3774,7 @@ +@@ -3804,7 +3804,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_WORKERS VARIABLE_SCOPE GLOBAL @@ -1324,7 +1324,7 @@ VARIABLE_COMMENT Alias for slave_parallel_threads NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3814,7 +3814,7 @@ +@@ -3844,7 +3844,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_TRANSACTION_RETRIES VARIABLE_SCOPE GLOBAL @@ -1333,7 +1333,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3834,7 +3834,7 @@ +@@ -3864,7 +3864,7 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_TRANSACTION_RETRY_INTERVAL VARIABLE_SCOPE GLOBAL @@ -1342,7 +1342,7 @@ VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3600 -@@ -3854,7 +3854,7 @@ +@@ -3884,7 +3884,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1351,7 +1351,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -4124,7 +4124,7 @@ +@@ -4154,7 +4154,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1360,7 +1360,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4224,7 +4224,7 @@ +@@ -4254,7 +4254,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1369,7 +1369,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -4234,7 +4234,7 @@ +@@ -4264,7 +4264,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1378,7 +1378,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -4294,7 +4294,7 @@ +@@ -4324,7 +4324,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1387,7 +1387,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4352,6 +4352,26 @@ +@@ -4382,6 +4382,26 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED @@ -1404,7 +1404,7 @@ +VARIABLE_NAME THREAD_POOL_MODE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM -+VARIABLE_COMMENT Chose implementation of the threadpool ++VARIABLE_COMMENT Chose implementation of the threadpool. Use 'windows' unless you have a workload with a lot of concurrent connections and minimal contention +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL @@ -1414,7 +1414,7 @@ VARIABLE_NAME THREAD_POOL_OVERSUBSCRIBE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE INT UNSIGNED -@@ -4455,7 +4475,7 @@ +@@ -4485,7 +4505,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TMPDIR VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR @@ -1423,7 +1423,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -4494,7 +4514,7 @@ +@@ -4524,7 +4544,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1432,7 +1432,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4504,7 +4524,7 @@ +@@ -4534,7 +4554,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1441,7 +1441,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4644,10 +4664,10 @@ +@@ -4674,10 +4694,10 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1454,7 +1454,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4671,7 +4691,7 @@ +@@ -4701,7 +4721,7 @@ order by variable_name; VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index e25a7df7591..b0cc6857fc9 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3645,7 +3645,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SECURE_FILE_PRIV VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory +VARIABLE_COMMENT Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory. Empty value means no limits except /proc NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv-master.opt b/mysql-test/suite/sys_vars/t/secure_file_priv.opt similarity index 100% rename from mysql-test/suite/sys_vars/t/secure_file_priv-master.opt rename to mysql-test/suite/sys_vars/t/secure_file_priv.opt diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv.test b/mysql-test/suite/sys_vars/t/secure_file_priv.test index bbbf01aae89..f1bc84576b5 100644 --- a/mysql-test/suite/sys_vars/t/secure_file_priv.test +++ b/mysql-test/suite/sys_vars/t/secure_file_priv.test @@ -1,10 +1,10 @@ +--source include/platform.inc --echo # --echo # Bug50373 --secure-file-priv="" --echo # CREATE TABLE t1 (c1 VARCHAR(50)); INSERT INTO t1 VALUES ("one"),("two"),("three"),("four"),("five"); SHOW VARIABLES LIKE 'secure_file_priv'; ---disable_query_log # Atempt to create a file where we normally aren't allowed to create one. # @@ -17,35 +17,23 @@ SHOW VARIABLES LIKE 'secure_file_priv'; # If we run tests with --mem, it will be /dev/shm. # If we run tests with --parallel, it will be mysql-test/var # (because MYSQLTEST_VARDIR in this case is mysql-test/var/N). ---disable_cursor_protocol - ---perl -use File::Basename; -my $protected_file= dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt'; -# Ensure bug50373.txt does not exist (e.g. leftover from previous -# test runs). -unlink $protected_file; -open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/bug50373.inc") or die; -print FILE "SELECT * FROM t1 INTO OUTFILE '".$protected_file."';\n"; -print FILE "DELETE FROM t1;\n"; -print FILE "LOAD DATA INFILE '".$protected_file."' INTO TABLE t1;\n"; -print FILE "SELECT * FROM t1;\n"; -print FILE "SELECT load_file('",$protected_file,"') AS loaded_file;\n"; -close(FILE); -EOF - ---enable_prepare_warnings ---source $MYSQL_TMP_DIR/bug50373.inc ---disable_prepare_warnings ---remove_file $MYSQL_TMP_DIR/bug50373.inc ---enable_query_log - ---enable_cursor_protocol +evalp SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/../bug50373.txt' FROM t1; +DELETE FROM t1; +evalp LOAD DATA INFILE '$MYSQLTEST_VARDIR/../bug50373.txt' INTO TABLE t1; +SELECT * FROM t1; +evalp SELECT load_file('$MYSQLTEST_VARDIR/../bug50373.txt') AS loaded_file; DROP TABLE t1; ---perl -use File::Basename; -unlink dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt'; -EOF +--remove_file $MYSQLTEST_VARDIR/../bug50373.txt +--echo # +--echo # MDEV-40589 default exclude list for secure-file-priv +--echo # +CREATE TABLE t1 (c1 VARCHAR(50)); +--disable_abort_on_error +LOAD DATA INFILE '/proc/cpuinfo' INTO TABLE t1; +--enable_abort_on_error +DROP TABLE t1; + +--echo # End of 10.6 tests diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc index a7b39f0ad16..804cded05c3 100644 --- a/plugin/file_key_management/parser.cc +++ b/plugin/file_key_management/parser.cc @@ -175,7 +175,7 @@ bool Parser::read_filekey(const char *filekey, char *secret) } close(f); - while (secret[len - 1] == '\r' || secret[len - 1] == '\n') len--; + while (len && (secret[len - 1] == '\r' || secret[len - 1] == '\n')) len--; if (len > MAX_SECRET_SIZE) { my_printf_error(EE_READ, diff --git a/plugin/qc_info/qc_info.cc b/plugin/qc_info/qc_info.cc index a73bc8ea9ec..0e1d86550f3 100644 --- a/plugin/qc_info/qc_info.cc +++ b/plugin/qc_info/qc_info.cc @@ -233,6 +233,7 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables, compile_time_assert(QUERY_CACHE_DB_LENGTH_SIZE == 2); db= key + statement_text_length + 1 + QUERY_CACHE_DB_LENGTH_SIZE; db_length= uint2korr(db - QUERY_CACHE_DB_LENGTH_SIZE); + set_if_smaller(db_length, (size_t)(key + key_length - QUERY_CACHE_FLAGS_SIZE - db)); table->field[COLUMN_STATEMENT_SCHEMA]->store(db, db_length, scs); diff --git a/plugin/type_mysql_json/mysql_json.cc b/plugin/type_mysql_json/mysql_json.cc index c28a403a603..6b267d404bd 100644 --- a/plugin/type_mysql_json/mysql_json.cc +++ b/plugin/type_mysql_json/mysql_json.cc @@ -373,7 +373,8 @@ static bool parse_mysql_scalar_or_value(String *buffer, const uchar *data, if (type_is_stored_inline(value_type, large)) { const size_t value_start = value_type_offset + 1; - if (parse_mysql_scalar(buffer, value_type, data + value_start, + if (value_start >= len || + parse_mysql_scalar(buffer, value_type, data + value_start, len - value_start)) return true; } @@ -383,7 +384,8 @@ static bool parse_mysql_scalar_or_value(String *buffer, const uchar *data, of the Object / Array */ const size_t value_start= read_offset_or_size( data + value_type_offset + 1, large); - if (parse_mysql_json_value(buffer, value_type, data + value_start, + if (value_start >= len || + parse_mysql_json_value(buffer, value_type, data + value_start, len - value_start, depth)) return true; } @@ -453,7 +455,7 @@ static bool parse_array_or_object(String *buffer, const uchar *data, size_t len, i * value_size(large)); /* First print the key. */ - if (buffer->append('"') || + if (key_start + key_len > bytes || buffer->append('"') || append_string_json(buffer, data + key_start, key_len) || buffer->append(STRING_WITH_LEN("\": "))) { diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf index 8f62cfd0cc9..5d24c7c00f9 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf +++ b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf @@ -26,6 +26,10 @@ wsrep_provider_options='base_port=@mysqld.2.#galera_port' wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' wsrep_node_name=test-node-2 +[sst] +# SSL mode is disabled for SST unless tests specifically enable it. +ssl-mode=DISABLED + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/scripts/galera_new_cluster.sh b/scripts/galera_new_cluster.sh index 4d27ff94e2a..98d23dd82f4 100755 --- a/scripts/galera_new_cluster.sh +++ b/scripts/galera_new_cluster.sh @@ -21,11 +21,17 @@ EOF exit 0 fi -echo _WSREP_NEW_CLUSTER='--wsrep-new-cluster' > "@INSTALL_RUNDATADIR@/wsrep-new-cluster" && \ +# INSTALL_RUNDIR, not the socket directory - the latter is writable by +# mariadbd, which could then inject arbitrary variables into the service +# environment. Removing the file here and not in the service file, +# because that runs as mysql and cannot unlink in /run. +new_cluster=@INSTALL_RUNDIR@/mariadb-wsrep-new-cluster +trap 'rm -f "$new_cluster"' EXIT +trap 'exit 1' HUP INT TERM + +echo _WSREP_NEW_CLUSTER='--wsrep-new-cluster' > "$new_cluster" && \ systemctl restart "${1:-mariadb.service}" extcode=$? -rm -f "@INSTALL_RUNDATADIR@/wsrep-new-cluster" - exit $extcode diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 7515ee029b3..b817565e827 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -571,6 +571,11 @@ read_cnf() if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then check_server_ssl_config fi + # MTR test hook: simulate a missing SSL certificate and key. + if [ -n "${MTR_SST_SIMULATE_NO_SSL_CERT:-}" ]; then + tpem="" + tkey="" + fi if [ "$tmode" != 'DISABLED' ]; then if [ 0 -eq $encrypt -a -n "$tpem" -a -n "$tkey" ] then @@ -599,6 +604,16 @@ read_cnf() "CERT='$tpem', KEY='$tkey', MODE='$tmode'," \ "encrypt='$encrypt'" + # ssl-mode requires encryption but none could be set up (no usable + # cert/key): abort instead of silently transferring in cleartext. + if [ "$tmode" != 'DISABLED' -a $encrypt -eq 0 ]; then + wsrep_log_error "ssl-mode is set to '$tmode', but no usable SSL" \ + "certificate and key were found. Cannot perform an" \ + "encrypted transfer. Please configure ssl-cert and" \ + "ssl-key, or set ssl-mode to DISABLED." + exit 22 # EINVAL + fi + if [ $encrypt -ge 2 ]; then ssl_dhparams=$(parse_cnf "$encgroups" 'ssl-dhparams') fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index a559c6749e9..faa8e592d65 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -197,14 +197,11 @@ SSTCAP="$tcap" SSLMODE=$(parse_cnf "$encgroups" 'ssl-mode' | tr '[[:lower:]]' '[[:upper:]]') if [ -z "$SSLMODE" ]; then - # Implicit verification if CA is set and the SSL mode - # is not specified by user: + # ssl-mode not set: derive it from the SSL config. Set it even when + # stunnel is absent, so the check below aborts instead of silently + # falling back to an unencrypted transfer. if [ -n "$SSTCA$SSTCAP" ]; then - STUNNEL_BIN=$(commandex 'stunnel') - if [ -n "$STUNNEL_BIN" ]; then - SSLMODE='VERIFY_CA' - fi - # Require SSL by default if SSL key and cert are present: + SSLMODE='VERIFY_CA' elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then SSLMODE='REQUIRED' fi @@ -279,10 +276,22 @@ if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then if [ -z "${STUNNEL_BIN+x}" ]; then STUNNEL_BIN=$(commandex 'stunnel') fi + # MTR test hook: simulate a missing stunnel binary. + if [ -n "${MTR_SST_SIMULATE_NO_STUNNEL:-}" ]; then + STUNNEL_BIN="" + fi if [ -n "$STUNNEL_BIN" ]; then wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA'," \ "CAPATH='$SSTCAP', ssl-mode='$SSLMODE'" STUNNEL="$STUNNEL_BIN $STUNNEL_CONF" + else + # Encryption required but stunnel missing: abort instead of + # silently falling back to an unencrypted transfer. + wsrep_log_error "ssl-mode is set to '$SSLMODE', but the 'stunnel'" \ + "binary was not found in the path. Cannot perform" \ + "an encrypted transfer. Please install stunnel or" \ + "set ssl-mode to DISABLED." + exit 2 # ENOENT fi fi diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 17122f8469a..5f0bd3969cd 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -163,7 +163,8 @@ String *Item_func_geometry_from_json::val_str(String *str) (const uchar *) js->end()); je.killed_ptr= (uint32_t *) ¤t_thd->killed; - if ((null_value= !Geometry::create_from_json(&buffer, &je, options==1, str))) + if (!json_read_value(&je) && + (null_value= !Geometry::create_from_json(&buffer, &je, options==1, str))) { int code= 0; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e980b79f5c5..52938056f0b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9126,45 +9126,39 @@ fn_format_relative_to_data_home(char * to, const char *name, bool is_secure_file_path(char *path) { - char buff1[FN_REFLEN], buff2[FN_REFLEN]; - size_t opt_secure_file_priv_len; - /* - All paths are secure if opt_secure_file_path is 0 - */ - if (!opt_secure_file_priv) - return TRUE; + char buf1[FN_REFLEN], buf2[FN_REFLEN]; + const char *cmp; - opt_secure_file_priv_len= strlen(opt_secure_file_priv); + if (opt_secure_file_priv) + cmp= opt_secure_file_priv; + else +#ifdef _WIN32 + return TRUE; // All paths are secure if opt_secure_file_priv is unset +#else + cmp= "/proc/"; // Check that it doesn't start with this prefix +#endif if (strlen(path) >= FN_REFLEN) return FALSE; - if (my_realpath(buff1, path, 0)) + if (my_realpath(buf1, path, 0)) { - /* - The supplied file path might have been a file and not a directory. - */ - size_t length= dirname_length(path); // Guaranteed to be < FN_REFLEN - memcpy(buff2, path, length); - buff2[length]= '\0'; - if (length == 0 || my_realpath(buff1, buff2, 0)) - return FALSE; - } - convert_dirname(buff2, buff1, NullS); - if (!lower_case_file_system) - { - if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len)) + /* The supplied file path might have been a file and not a directory. */ + size_t length= dirname_length(path); // Guaranteed to be < FN_REFLEN + memcpy(buf2, path, length); + buf2[length]= '\0'; + if (length == 0 || my_realpath(buf1, buf2, 0)) return FALSE; } + convert_dirname(buf2, buf1, NullS); + + size_t cmp_len= strlen(cmp); + bool matched; + if (lower_case_file_system) + matched= !files_charset_info->strnncoll(buf2, strlen(buf2), cmp, cmp_len, 1); else - { - if (files_charset_info->strnncoll(buff2, strlen(buff2), - opt_secure_file_priv, - opt_secure_file_priv_len, - TRUE)) - return FALSE; - } - return TRUE; + matched= !strncmp(cmp, buf2, cmp_len); + return opt_secure_file_priv ? matched : !matched; } diff --git a/sql/slave.cc b/sql/slave.cc index 1d3573980ec..3af008a77eb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3393,10 +3393,13 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, protocol->store(mi->connection_name.str, mi->connection_name.length, &my_charset_bin); - mysql_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->rli.run_lock); THD *sql_thd= mi->rli.sql_driver_thd; + DEBUG_SYNC(thd, "hold_sss_with_run_lock"); const char *slave_sql_running_state= sql_thd ? sql_thd->get_proc_info() : ""; + mysql_mutex_unlock(&mi->rli.run_lock); + mysql_mutex_lock(&mi->run_lock); THD *io_thd= mi->io_thd; const char *slave_io_running_state= io_thd ? io_thd->get_proc_info() : ""; mysql_mutex_unlock(&mi->run_lock); diff --git a/sql/spatial.cc b/sql/spatial.cc index 979bac09545..1484ae3d322 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -493,19 +493,14 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, json_engine_t *je, bool er_on_3D, String *res) { Class_info *ci= NULL; - const uchar *coord_start= NULL, *geom_start= NULL, - *features_start= NULL, *geometry_start= NULL; + enum t_enum { T_NONE, T_GEOMETRY, T_GEOMETRIES, T_COORD, T_FEATURE }; + enum t_enum arg= T_NONE; + json_engine_t argje, *je_arg; Geometry *result; uchar key_buf[max_keyname_len]; uint key_len; - int fcoll_type_found= 0, feature_type_found= 0; + bool feature_type_found= false; - const uint32_t *killed_ptr= (uint32_t *) je->killed_ptr; - int stack_p; - - if (json_read_value(je)) - goto err_return; - if (je->value_type != JSON_VALUE_OBJECT) { je->s.error= GEOJ_INCORRECT_GEOJSON; @@ -514,7 +509,8 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, while (json_scan_next(je) == 0 && je->state != JST_OBJ_END) { - DBUG_ASSERT(je->state == JST_KEY); + if (je->state != JST_KEY) + break; key_len=0; while (json_read_keyname_chr(je) == 0) @@ -543,31 +539,36 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, if (je->value_type == JSON_VALUE_STRING) { - if ((ci= find_class((const char *) je->value, je->value_len))) + if ((ci= find_class(reinterpret_cast(je->value), je->value_len))) { - if ((coord_start= - (ci == &geometrycollection_class) ? geom_start : coord_start)) + if ((ci == &geometrycollection_class && arg == T_GEOMETRIES) || arg == T_COORD) goto create_geom; + if (arg != T_NONE) + break; /* invalid arg present for current geometry */ } else if (je->value_len == feature_coll_type_len && my_charset_latin1.strnncoll(je->value, je->value_len, - feature_coll_type, feature_coll_type_len) == 0) + feature_coll_type, feature_coll_type_len) == 0) { /* - 'FeatureCollection' type found. Handle the 'Featurecollection'/'features' - GeoJSON construction. + 'FeatureCollection' type found. Handle the 'Featurecollection' + /'features' GeoJSON construction. */ - if (features_start) - goto handle_feature_collection; - fcoll_type_found= 1; + ci= &geometrycollection_class; + if (arg == T_FEATURE) + goto create_geom; + if (arg != T_NONE) + break; /* invalid arg present for current geometry */ } else if (je->value_len == feature_type_len && my_charset_latin1.strnncoll(je->value, je->value_len, - feature_type, feature_type_len) == 0) + feature_type, feature_type_len) == 0) { - if (geometry_start) + if (arg == T_GEOMETRY) goto handle_geometry_key; - feature_type_found= 1; + feature_type_found= true; + if (arg != T_NONE) + break; /* invalid arg present for current geometry */ } else /* can't understand the type. */ break; @@ -578,6 +579,8 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, else if (key_len == coord_keyname_len && memcmp(key_buf, coord_keyname, coord_keyname_len) == 0) { + if (arg != T_NONE) + break; /* previous arg unprocessed */ /* Found the "coordinates" key. Let's check it's an array and remember where it starts. @@ -587,16 +590,25 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, if (je->value_type == JSON_VALUE_ARRAY) { - coord_start= je->value_begin; + arg= T_COORD; if (ci && ci != &geometrycollection_class) - goto create_geom; + { + je_arg= je; + goto create_geom; + } + argje= *je; + je_arg= &argje; if (json_skip_level(je)) goto err_return; } + else + break; /* coordinates needs to be an array */ } else if (key_len == geometries_keyname_len && memcmp(key_buf, geometries_keyname, geometries_keyname_len) == 0) { + if (arg != T_NONE) + break; /* previous arg unprocessed */ /* Found the "geometries" key. Let's check it's an array and remember where it starts. @@ -606,17 +618,28 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, if (je->value_type == JSON_VALUE_ARRAY) { - geom_start= je->value_begin; if (ci == &geometrycollection_class) { - coord_start= geom_start; + je_arg= je; goto create_geom; } + if (ci != nullptr) + break; /* geometries only valid inside geometrycollation */ + arg= T_GEOMETRIES; + argje= *je; + je_arg= &argje; + /* skip geometries for now and search for type */ + if (json_skip_level(je)) + goto err_return; } + else + break; /* geometries needs to be an array */ } else if (key_len == features_keyname_len && memcmp(key_buf, features_keyname, features_keyname_len) == 0) { + if (arg != T_NONE) + break; /* previous arg unprocessed */ /* 'features' key found. Handle the 'Featurecollection'/'features' GeoJSON construction. @@ -625,10 +648,23 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, goto err_return; if (je->value_type == JSON_VALUE_ARRAY) { - features_start= je->value_begin; - if (fcoll_type_found) - goto handle_feature_collection; + if (ci == &geometrycollection_class) + { + je_arg= je; + goto create_geom; + } + if (ci != nullptr) + break; /* features only valid inside featurecollation */ + + arg= T_FEATURE; + argje= *je; + je_arg= &argje; + /* skip features for now and search for type */ + if (json_skip_level(je)) + goto err_return; } + else + break; /* feature collections needs to be an array */ } else if (key_len == geometry_keyname_len && memcmp(key_buf, geometry_keyname, geometry_keyname_len) == 0) @@ -637,12 +673,21 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, goto err_return; if (je->value_type == JSON_VALUE_OBJECT) { - geometry_start= je->value_begin; if (feature_type_found) + { + je_arg= je; goto handle_geometry_key; + } + if (ci != nullptr) + break; /* geometry only valid inside feature */ + arg= T_GEOMETRY; + argje= *je; + je_arg= &argje; + if (json_skip_level(je)) + goto err_return; } else - goto err_return; + break; /* geometry needs to be an object */ } else { @@ -661,35 +706,35 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, } goto err_return; -handle_feature_collection: - ci= &geometrycollection_class; - coord_start= features_start; - create_geom: - stack_p= je->stack_p; - json_scan_start(je, je->s.cs, coord_start, je->s.str_end); - je->killed_ptr= killed_ptr; - je->stack_p= stack_p; - if (res->reserve(1 + 4, 512)) goto err_return; result= (*ci->m_create_func)(buffer->data); res->q_append((char) wkb_ndr); res->q_append((uint32) result->get_class_info()->m_type_id); - if (result->init_from_json(je, er_on_3D, res)) + if (result->init_from_json(je_arg, er_on_3D, res)) + { + if (je_arg != je) /* copy error out of copied engine */ + *je= *je_arg; + goto err_return; + } + /* finish of the object scan for validation/geomcollection */ + if (json_skip_level(je)) goto err_return; return result; -handle_geometry_key: - stack_p= je->stack_p; - json_scan_start(je, je->s.cs, geometry_start, je->s.str_end); - je->killed_ptr= killed_ptr; - je->stack_p= stack_p; - return create_from_json(buffer, je, er_on_3D, res); +handle_geometry_key: /* feature */ + result= create_from_json(buffer, je_arg, er_on_3D, res); + + /* skip rest of feature - can be arbitrary fields */ + if (json_skip_level(je)) + goto err_return; + + return result; err_return: return NULL; } @@ -964,7 +1009,6 @@ static int read_point_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - DBUG_ASSERT(je->state == JST_VALUE); if (json_read_value(je)) return 1; @@ -978,6 +1022,8 @@ static int read_point_from_json(json_engine_t *je, bool er_on_3D, n_coord++; } + if (je->s.error != 0) + return 1; if (n_coord <= 2 || !er_on_3D) return 0; je->s.error= Geometry::GEOJ_DIMENSION_NOT_SUPPORTED; @@ -991,8 +1037,6 @@ bad_coordinates: bool Gis_point::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) { double x, y; - if (json_read_value(je)) - return TRUE; if (je->value_type != JSON_VALUE_ARRAY) { @@ -1006,6 +1050,7 @@ bool Gis_point::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) wkb->q_append(x); wkb->q_append(y); + /* Note GEOJSON RFC7946 3.3.1 - 3D possible, but not WKB? */ return FALSE; } @@ -1282,11 +1327,9 @@ bool Gis_line_string::init_from_json(json_engine_t *je, bool er_on_3D, uint32 np_pos= wkb->length(); Gis_point p; - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -1297,7 +1340,13 @@ bool Gis_line_string::init_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state != JST_VALUE) + goto err_geoj_incorrect; + + if (json_read_value(je)) + return TRUE; + if (je->value_type != JSON_VALUE_ARRAY) + goto err_geoj_incorrect; if (p.init_from_json(je, er_on_3D, wkb)) return TRUE; @@ -1676,11 +1725,9 @@ bool Gis_polygon::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) uint32 lr_pos= wkb->length(); int closed; - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -1692,11 +1739,18 @@ bool Gis_polygon::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { Gis_line_string ls; - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state != JST_VALUE) + goto err_geoj_incorrect; + + if (json_read_value(je)) + return TRUE; + if (je->value_type != JSON_VALUE_ARRAY) + goto err_geoj_incorrect; uint32 ls_pos=wkb->length(); if (ls.init_from_json(je, er_on_3D, wkb)) return TRUE; + ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); if (ls.is_closed(&closed) || !closed) { @@ -2197,11 +2251,9 @@ bool Gis_multi_point::init_from_json(json_engine_t *je, bool er_on_3D, uint32 np_pos= wkb->length(); Gis_point p; - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -2212,7 +2264,12 @@ bool Gis_multi_point::init_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state != JST_VALUE) + goto err_geoj_incorrect; + if (json_read_value(je)) + return TRUE; + if (je->value_type != JSON_VALUE_ARRAY) + goto err_geoj_incorrect; if (wkb->reserve(1 + 4, 512)) return TRUE; @@ -2562,11 +2619,9 @@ bool Gis_multi_line_string::init_from_json(json_engine_t *je, bool er_on_3D, uint32 n_line_strings= 0; uint32 ls_pos= wkb->length(); - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -2577,9 +2632,14 @@ bool Gis_multi_line_string::init_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - Gis_line_string ls; - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state != JST_VALUE) + goto err_geoj_incorrect; + if (json_read_value(je)) + return TRUE; + if (je->value_type != JSON_VALUE_ARRAY) + goto err_geoj_incorrect; + Gis_line_string ls; if (wkb->reserve(1 + 4, 512)) return TRUE; wkb->q_append((char) wkb_ndr); @@ -2968,11 +3028,9 @@ bool Gis_multi_polygon::init_from_json(json_engine_t *je, bool er_on_3D, int np_pos= wkb->length(); Gis_polygon p; - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -2983,7 +3041,12 @@ bool Gis_multi_polygon::init_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state != JST_VALUE) + goto err_geoj_incorrect; + if (json_read_value(je)) + return TRUE; + if (je->value_type != JSON_VALUE_ARRAY) + goto err_geoj_incorrect; if (wkb->reserve(1 + 4, 512)) return TRUE; @@ -3427,6 +3490,9 @@ uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, return 0; n_geom= wkb_get_uint(wkb, bo); + if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&wkb_orig)) + return 1; + if (res->reserve(4, 512)) return 0; res->q_append(n_geom); @@ -3467,11 +3533,9 @@ bool Gis_geometry_collection::init_from_json(json_engine_t *je, bool er_on_3D, Geometry_buffer buffer; Geometry *g; - if (json_read_value(je)) - return TRUE; - if (je->value_type != JSON_VALUE_ARRAY) { +err_geoj_incorrect: je->s.error= GEOJ_INCORRECT_GEOJSON; return TRUE; } @@ -3482,17 +3546,17 @@ bool Gis_geometry_collection::init_from_json(json_engine_t *je, bool er_on_3D, while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) { - json_engine_t sav_je= *je; - - DBUG_ASSERT(je->state == JST_VALUE); + if (je->state == JST_VALUE) + { + if (json_read_value(je)) + return TRUE; + } + if (je->state != JST_OBJ_START) + goto err_geoj_incorrect; if (!(g= create_from_json(&buffer, je, er_on_3D, wkb))) return TRUE; - *je= sav_je; - if (json_skip_array_item(je)) - return TRUE; - n_objects++; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d7782dea96e..c6a4302dabf 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3797,7 +3797,7 @@ privilege_t acl_get(const char *host, const char *ip, acl_entry *entry; DBUG_ENTER("acl_get"); - tmp_db= strmov(strmov(key, safe_str(ip)) + 1, user) + 1; + tmp_db= strmov(strmov(key, safe_str(ip ? ip : host)) + 1, user) + 1; end= strnmov(tmp_db, db, key + sizeof(key) - tmp_db); if (end >= key + sizeof(key)) // db name was truncated @@ -11922,6 +11922,61 @@ Silence_routine_definer_errors::handle_condition( } +/* + The low level function to revoke routine privileges for the given sp handler + @param thd the thd + @param proc_privs the table mysql.proc_privs + @param sp_db the routine database + @param sp_name the routine name + @param sph the sp handler +*/ +static void sp_revoke_privileges_for_handler(THD *thd, TABLE *proc_privs, +#if MYSQL_VERSION_ID < 110501 + const char *sp_db, + const char *sp_name, +#else +#error Remove the above conditional code + const Lex_ident_db &sp_db, + const Lex_ident_routine &sp_name, +#endif + const Sp_handler *sph) +{ + uint counter, revoked; + HASH *hash= sph->get_priv_hash(); + do + { + for (counter= 0, revoked= 0 ; counter < hash->records ; ) + { + GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); +#if MYSQL_VERSION_ID < 110501 + if (!my_strcasecmp(&my_charset_utf8mb3_bin, grant_proc->db, sp_db) && + !my_strcasecmp(system_charset_info, grant_proc->tname, sp_name)) +#else +#error Remove the above conditional code + if (sp_db.streq(Lex_cstring_strlen(grant_proc->db)) && + sp_name.streq(Lex_cstring_strlen(grant_proc->tname))) +#endif + { + LEX_USER lex_user; + lex_user.user.str= grant_proc->user; + lex_user.user.length= strlen(grant_proc->user); + lex_user.host.str= safe_str(grant_proc->host.hostname); + lex_user.host.length= strlen(lex_user.host.str); + if (replace_routine_table(thd, grant_proc, + proc_privs, lex_user, + grant_proc->db, grant_proc->tname, + sph, ALL_KNOWN_ACL, 1) == 0) + { + revoked= 1; + continue; + } + } + counter++; + } + } while (revoked); +} + + /** Revoke privileges for all users on a stored procedure. Use an error handler that converts errors about missing grants into warnings. @@ -11942,9 +11997,7 @@ Silence_routine_definer_errors::handle_condition( bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, const Sp_handler *sph) { - uint counter, revoked; int result; - HASH *hash= sph->get_priv_hash(); Silence_routine_definer_errors error_handler; DBUG_ENTER("sp_revoke_privileges"); @@ -11964,31 +12017,12 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, mysql_mutex_lock(&acl_cache->lock); /* Remove procedure access */ - do - { - for (counter= 0, revoked= 0 ; counter < hash->records ; ) - { - GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); - if (!my_strcasecmp(&my_charset_utf8mb3_bin, grant_proc->db, sp_db) && - !my_strcasecmp(system_charset_info, grant_proc->tname, sp_name)) - { - LEX_USER lex_user; - lex_user.user.str= grant_proc->user; - lex_user.user.length= strlen(grant_proc->user); - lex_user.host.str= safe_str(grant_proc->host.hostname); - lex_user.host.length= strlen(lex_user.host.str); - if (replace_routine_table(thd, grant_proc, - tables.procs_priv_table().table(), lex_user, - grant_proc->db, grant_proc->tname, - sph, ALL_KNOWN_ACL, 1) == 0) - { - revoked= 1; - continue; - } - } - counter++; - } - } while (revoked); + if (sph == &sp_handler_package_spec) + sp_revoke_privileges_for_handler(thd, tables.procs_priv_table().table(), + sp_db, sp_name, &sp_handler_package_body); + + sp_revoke_privileges_for_handler(thd, tables.procs_priv_table().table(), + sp_db, sp_name, sph); mysql_mutex_unlock(&acl_cache->lock); mysql_rwlock_unlock(&LOCK_grant); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 160d7d4776d..eabad77012a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2247,7 +2247,7 @@ retry_share: goto retry_share; } - if (thd->open_tables && thd->open_tables->s->tdc->flushed) + if (!table_list->sequence && thd->open_tables && thd->open_tables->s->tdc->flushed) { /* If the version changes while we're opening the tables, @@ -5350,6 +5350,10 @@ bool open_and_lock_internal_tables(TABLE *table, bool lock_table) MYSQL_LOCK_USE_MALLOC)) goto err; + /* no existing lock to merge with */ + if (save_lock == nullptr) + DBUG_RETURN(0); + if (!(new_lock= mysql_lock_merge(save_lock, thd->lock))) { thd->lock= save_lock; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 0d87c830adf..b600e50f09a 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -781,10 +781,22 @@ bool select_unit_ext::send_eof() next_sl && next_sl->get_linkage() == INTERSECT_TYPE && !next_sl->distinct; + /* + True at the last INTERSECT of an inline INTERSECT DISTINCT subsequence: the + records that did not match every operand (their intersect counter differs + from curr_step) must be dropped. Instead of a separate table scan this is + folded into the scan/unfold loops below, so the table is scanned only once + (MDEV-38722). When the subsequence is materialized in a derived table this + filtering is done by select_unit::send_eof() instead. + */ + bool filter_intersect= curr_op_type == INTERSECT_DISTINCT && + !(next_sl && + next_sl->get_linkage() == INTERSECT_TYPE); bool need_unfold= disable_index_if_needed(curr_sl); if (((curr_sl->distinct && !is_next_distinct) || curr_op_type == INTERSECT_ALL || + filter_intersect || is_next_intersect_all) && !need_unfold) { @@ -806,6 +818,13 @@ bool select_unit_ext::send_eof() } break; } + if (filter_intersect && additional_cnt->val_int() != curr_step) + { + /* drop a record that did not match every INTERSECT operand */ + if (unlikely(error= delete_record())) + break; + continue; + } store_record(table, record[1]); if (curr_sl->distinct && !is_next_distinct) @@ -859,6 +878,13 @@ bool select_unit_ext::send_eof() } break; } + if (filter_intersect && additional_cnt->val_int() != curr_step) + { + /* drop a record that did not match every INTERSECT operand */ + if (unlikely(error= delete_record())) + break; + continue; + } dup_cnt= (ha_rows)duplicate_cnt->val_int(); /* delete record if not exist in the second operand */ if (dup_cnt == 0) @@ -1999,6 +2025,15 @@ void st_select_lex_unit::optimize_bag_operation(bool is_outer_distinct) sl->distinct= true; disable_index= sl; } + else if (disable_index) + { + /* + EXCEPT ALL needs the unique index in select_unit_ext::send_data(). + If the index would otherwise be released at an earlier node, + postpone the release until (at least) this operation. + */ + disable_index= sl; + } } } else diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index db759c37017..957e231c25d 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3484,11 +3484,15 @@ static Sys_var_mybool Sys_require_secure_transport( ON_CHECK(check_require_secure_transport), ON_UPDATE(0)); static Sys_var_charptr_fscs Sys_secure_file_priv( - "secure_file_priv", - "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files " - "within specified directory", - PREALLOCATED READ_ONLY GLOBAL_VAR(opt_secure_file_priv), - CMD_LINE(REQUIRED_ARG, OPT_SEQURE_FILE_PRIV), DEFAULT(0)); + "secure_file_priv", + "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files " + "within specified directory." +#ifndef _WIN32 + " Empty value means no limits except /proc" +#endif + , + PREALLOCATED READ_ONLY GLOBAL_VAR(opt_secure_file_priv), + CMD_LINE(REQUIRED_ARG, OPT_SEQURE_FILE_PRIV), DEFAULT(0)); static bool check_server_id(sys_var *self, THD *thd, set_var *var) { diff --git a/sql/table.cc b/sql/table.cc index f52f0590dea..d46d81b4512 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -114,10 +114,8 @@ static std::atomic last_table_id; /* Functions defined in this file */ -static bool fix_type_pointers(const char ***typelib_value_names, - uint **typelib_value_lengths, - TYPELIB *point_to_type, uint types, - char *names, size_t names_length); +static bool fix_type_pointers(const char ***, const char **, uint **, + TYPELIB *, uint, char *, size_t); static field_index_t find_field(Field **fields, uchar *record, uint start, uint length); @@ -770,7 +768,7 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, uint i, j, n_length; KEY_PART_INFO *key_part= NULL; ulong *rec_per_key= NULL; - KEY_PART_INFO *first_key_part= NULL; + KEY_PART_INFO *first_key_part= NULL, *key_part_end; uint first_key_parts= 0; if (!keys) @@ -778,7 +776,7 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, len))) return 1; bzero((char*) keyinfo, len); - key_part= reinterpret_cast (keyinfo); + key_part_end= key_part= reinterpret_cast (keyinfo); } /* @@ -834,6 +832,7 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, sizeof(ulong) * *ext_key_parts))) return 1; first_key_part= key_part; + key_part_end= key_part + *ext_key_parts; first_key_parts= first_keyinfo->user_defined_key_parts; keyinfo->flags= first_keyinfo->flags; keyinfo->key_length= first_keyinfo->key_length; @@ -847,6 +846,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, keyinfo->rec_per_key= rec_per_key; for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++) { + if (key_part >= key_part_end) + return 1; if (strpos + (new_frm_ver >= 1 ? 9 : 7) >= frm_image_end) return 1; if (!(keyinfo->algorithm == HA_KEY_ALG_LONG_HASH)) @@ -904,6 +905,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, } if (curr_key_part == curr_key_part_end) { + if (key_part >= key_part_end) + return 1; *key_part++= first_key_part[j]; *rec_per_key++= 0; keyinfo->ext_key_parts++; @@ -917,13 +920,17 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, share->ext_key_parts++; share->ext_key_parts+= keyinfo->ext_key_parts; } - keynames->str= (char*) key_part; - keynames->length= strnmov(keynames->str, (char *) strpos, - frm_image_end - strpos) - keynames->str; - strpos+= keynames->length; - if (*strpos++) // key names are \0-terminated + if (key_part > key_part_end) return 1; - keynames->length++; // Include '\0', to make fix_type_pointers() happy. + size_t max_keyname_len= MY_MIN(len, (uint)(frm_image_end - strpos)); + keynames->str= (char*) key_part; + keynames->length= strnmov(keynames->str, (char *)strpos, + max_keyname_len) - keynames->str; + if (keynames->length >= max_keyname_len) + return 1; // meaning key name was not \0-terminated + keynames->length++; // include '\0', to make fix_type_pointers() happy. + strpos+= keynames->length; + len-= (uint)keynames->length; //reading index comments for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++) @@ -935,11 +942,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, keyinfo->comment.length= uint2korr(strpos); strpos+= 2; - if (strpos + keyinfo->comment.length >= frm_image_end) + if (strpos + keyinfo->comment.length >= frm_image_end || + keyinfo->comment.length > len) return 1; keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos, keyinfo->comment.length); strpos+= keyinfo->comment.length; + len-= (uint)keyinfo->comment.length; } DBUG_ASSERT(MY_TEST(keyinfo->flags & HA_USES_COMMENT) == (keyinfo->comment.length > 0)); @@ -1058,7 +1067,8 @@ static void mysql57_calculate_null_position(TABLE_SHARE *share, uchar **null_pos, uint *null_bit_pos, const uchar *strpos, - const uchar *vcol_screen_pos) + const uchar *vcol_screen_pos, + const uchar *vcol_screen_end) { uint field_pack_length= 17; @@ -1069,6 +1079,8 @@ static void mysql57_calculate_null_position(TABLE_SHARE *share, if ((strpos[10] & MYSQL57_GENERATED_FIELD)) { + if (vcol_screen_pos + MYSQL57_GCOL_HEADER_SIZE >= vcol_screen_end) + return; /* Skip virtual (not stored) generated field */ bool stored_in_db= vcol_screen_pos[3]; vcol_screen_pos+= (uint2korr(vcol_screen_pos + 1) + @@ -1788,6 +1800,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, const uchar *forminfo; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos); + uchar *data_start, *data_end; + uchar *first_stored= 0, *first_virtual= 0, *next_stored= 0, *next_virtual= 0; const uchar *disk_buff, *strpos; ulong pos, record_offset; ulong rec_buff_length; @@ -1795,13 +1809,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, KEY *keyinfo; KEY_PART_INFO *key_part= NULL; Field **field_ptr, *reg_field; - const char **interval_array; + const char **interval_array, **interval_array_end; uint *typelib_value_lengths= NULL; enum legacy_db_type legacy_db_type; my_bitmap_map *bitmaps; bool null_bits_are_used; uint vcol_screen_length; - uchar *vcol_screen_pos; + uchar *vcol_screen_pos, *vcol_screen_end; LEX_CUSTRING options; LEX_CSTRING se_name= empty_clex_str; KEY first_keyinfo; @@ -1811,7 +1825,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, bool vers_can_native= false, frm_created= 0; Field_data_type_info_array field_data_type_info_array; MEM_ROOT *old_root= thd->mem_root; - Virtual_column_info **table_check_constraints; + Virtual_column_info **table_check_constr; bool *interval_unescaped= NULL; extra2_fields extra2; bool extra_index_flags_present= FALSE; @@ -1852,6 +1866,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, /* Length of the MariaDB extra2 segment in the form file. */ len = uint2korr(frm_image+4); + if (frm_length < FRM_HEADER_SIZE + len || + !(pos= uint4korr(frm_image + FRM_HEADER_SIZE + len))) + goto err; + + forminfo= frm_image + pos; + if (forminfo + FRM_FORMINFO_SIZE >= frm_image_end) + goto err; + if (read_extra2(frm_image, len, &extra2)) goto err; @@ -1871,17 +1893,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (!share->default_part_plugin) goto err; } -#endif - if (frm_length < FRM_HEADER_SIZE + len || - !(pos= uint4korr(frm_image + FRM_HEADER_SIZE + len))) - goto err; - - forminfo= frm_image + pos; - if (forminfo + FRM_FORMINFO_SIZE >= frm_image_end) - goto err; - -#ifdef WITH_PARTITION_STORAGE_ENGINE if (frm_image[61] && !share->default_part_plugin) { enum legacy_db_type db_type= (enum legacy_db_type) (uint) frm_image[61]; @@ -1973,6 +1985,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, share->keys_in_use.init(keys); ext_key_parts= key_parts; + if ((key_parts && !keys) || key_parts < keys) + goto err; + if (extra2.index_flags.str && extra2.index_flags.length != keys) goto err; @@ -2129,12 +2144,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, { //reading long table comment if (next_chunk + 2 > buff_end) - { - DBUG_PRINT("error", - ("long table comment is not defined in .frm")); goto err; - } share->comment.length = uint2korr(next_chunk); + if (next_chunk + 2 + share->comment.length > buff_end) + goto err; if (! (share->comment.str= strmake_root(&share->mem_root, (char*)next_chunk + 2, share->comment.length))) { @@ -2143,17 +2156,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, next_chunk+= 2 + share->comment.length; } - DBUG_ASSERT(next_chunk <= buff_end); - if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS_legacy) { if (options.str) goto err; + if (next_chunk + 4 > buff_end) + goto err; options.length= uint4korr(next_chunk); options.str= next_chunk + 4; next_chunk+= options.length + 4; + if (next_chunk > buff_end) + goto err; } - DBUG_ASSERT(next_chunk <= buff_end); } else { @@ -2165,7 +2179,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, share->key_block_size= uint2korr(frm_image+62); keyinfo= share->key_info; - if (extra2.index_flags.str) extra_index_flags_present= TRUE; @@ -2210,6 +2223,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, disk_buff= frm_image + pos + FRM_FORMINFO_SIZE; share->fields= uint2korr(forminfo+258); + if (share->fields <= 0 || share->fields > MAX_FIELDS) + goto err; if (extra2.field_flags.str && extra2.field_flags.length != share->fields) goto err; pos= uint2korr(forminfo+260); /* Length of all screens */ @@ -2231,6 +2246,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, share->comment.length); } + if (hash_fields > share->fields || share->null_fields > share->fields) + goto err; + DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length)); /* @@ -2255,12 +2273,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, &share->field, (uint)(share->fields+1)*sizeof(Field*), &share->intervals, (uint)interval_count*sizeof(TYPELIB), &share->check_constraints, (uint) share->table_check_constraints * sizeof(Virtual_column_info*), - /* - This looks wrong: shouldn't it be (+2+interval_count) - instread of (+3) ? - */ - &interval_array, (uint) (share->fields+interval_parts+ keys+3)*sizeof(char *), - &typelib_value_lengths, total_typelib_value_count * sizeof(uint *), + &interval_array, (uint)total_typelib_value_count * sizeof(char *), + &typelib_value_lengths, (uint)total_typelib_value_count * sizeof(uint), &names, (uint) (n_length+int_length), &comment_pos, (uint) com_length, &vcol_screen_pos, vcol_screen_length, @@ -2276,10 +2290,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } field_ptr= share->field; - table_check_constraints= share->check_constraints; + interval_array_end= interval_array + total_typelib_value_count; + table_check_constr= share->check_constraints; read_length=(uint) (share->fields * field_pack_length + pos+ (uint) (n_length+int_length+com_length+ vcol_screen_length)); + if (disk_buff + read_length > frm_image_end) + goto err; strpos= disk_buff+pos; if (!interval_count) @@ -2293,21 +2310,24 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, com_length); memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length, vcol_screen_length); + vcol_screen_end= vcol_screen_pos + vcol_screen_length; - if (fix_type_pointers(&interval_array, &typelib_value_lengths, - &share->fieldnames, 1, names, n_length) || + if (fix_type_pointers(&interval_array, interval_array_end, + &typelib_value_lengths, &share->fieldnames, 1, names, + n_length) || share->fieldnames.count != share->fields) goto err; - if (fix_type_pointers(&interval_array, &typelib_value_lengths, - share->intervals, interval_count, - names + n_length, int_length)) + if (fix_type_pointers(&interval_array, interval_array_end, + &typelib_value_lengths, share->intervals, + interval_count, names + n_length, int_length)) goto err; - if (keynames.length && - (fix_type_pointers(&interval_array, &typelib_value_lengths, - &share->keynames, 1, keynames.str, keynames.length) || - share->keynames.count != keys)) + if ((keynames.length && + fix_type_pointers(&interval_array, interval_array_end, + &typelib_value_lengths, &share->keynames, 1, + keynames.str, keynames.length)) || + share->keynames.count != keys) goto err; /* Allocate handler */ @@ -2331,14 +2351,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, */ share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8; } -#ifndef WE_WANT_TO_SUPPORT_VERY_OLD_FRM_FILES else { share->null_bytes= (share->null_fields+7)/8; null_flags= null_pos= record + 1 + share->reclength - share->null_bytes; null_bit_pos= 0; } -#endif use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH; if (use_hash) @@ -2359,7 +2377,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, mysql57_vcol_null_bit_pos= null_bit_pos; mysql57_calculate_null_position(share, &mysql57_vcol_null_pos, &mysql57_vcol_null_bit_pos, - strpos, vcol_screen_pos); + strpos, vcol_screen_pos, vcol_screen_end); } /* Set system versioning information. */ @@ -2408,20 +2426,22 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (extra2.without_overlaps.str) { - if (extra2.application_period.str == NULL) + if (extra2.application_period.str == NULL || + extra2.without_overlaps.length < frm_keyno_size) goto err; const uchar *key_pos= extra2.without_overlaps.str; period.unique_keys= read_frm_keyno(key_pos); + if (period.unique_keys > keys || + extra2.without_overlaps.length != (period.unique_keys+1)*frm_keyno_size) + goto err; for (uint k= 0; k < period.unique_keys; k++) { key_pos+= frm_keyno_size; uint key_nr= read_frm_keyno(key_pos); + if (key_nr >= keys) + goto err; key_info[key_nr].without_overlaps= true; } - - if ((period.unique_keys + 1) * frm_keyno_size - != extra2.without_overlaps.length) - goto err; } if (extra2.field_data_type_info.length && @@ -2455,6 +2475,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, comment.str= (char*) comment_pos; comment.length= comment_length; comment_pos+= comment_length; + if (com_length < comment_length) + goto err; + com_length-= comment_length; } if (strpos[13] == MYSQL_TYPE_VIRTUAL && @@ -2467,7 +2490,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, */ uint vcol_info_length= (uint) strpos[12]; - if (!vcol_info_length) // Expect non-null expression + if (vcol_info_length < 4 || + vcol_screen_pos + vcol_info_length > vcol_screen_end) goto err; attr.frm_unpack_basic(strpos); @@ -2569,15 +2593,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, byte 4 = stored_in_db byte 5.. = expr */ - if ((uint)(vcol_screen_pos)[0] != 1) + if (vcol_screen_pos + MYSQL57_GCOL_HEADER_SIZE > vcol_screen_end || + vcol_screen_pos[0] != 1) goto err; vcol_info= new (&share->mem_root) Virtual_column_info(); uint vcol_info_length= uint2korr(vcol_screen_pos + 1); - if (!vcol_info_length) // Expect non-empty expression - goto err; vcol_info->stored_in_db= vcol_screen_pos[3]; vcol_info->utf8= 0; vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;; + if (!vcol_info_length || // Expect non-empty expression + vcol_screen_pos > vcol_screen_end) + goto err; share->virtual_fields++; } } @@ -2634,6 +2660,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL; } + if (interval_nr > interval_count) + goto err; + if (interval_nr && (attr.charset->mbminlen > 1 || (attr.pack_flag & FIELDFLAG_FRM_HEX_ENCODED_TYPELIB))) { @@ -2735,6 +2764,52 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (!reg_field) // Not supported field type goto err; + /* + Verify that fields follow one another in the record without overlaps. + That is the next field starts where the previous field ended. + Virtual fields complicate the check. Stored fields follow each other in + the record order, virtual fields also follow each in the record order + but they're always at the end of the record, and can be interleaved + with normal fields in the table. + + We detect this dynamically - as long as the next field starts where the + previous ended, assume they're normal fields. When the next field starts + with a gap - it's the first virtual (and the future virtual fields must + follow that field). If the next field starts before the previous - it + means the table started from virtual fields and this is the first stored + field. Either ("gap" or "before") can happen only once. + */ + if (!next_stored) // first field, i == 0 + { + first_stored= reg_field->ptr; + next_stored= first_stored + reg_field->pack_length_in_rec(); + } + else if (reg_field->ptr == next_stored) // next stored field + next_stored+= reg_field->pack_length_in_rec(); + else if (reg_field->ptr > next_stored) // virtual + { + if (next_virtual) + { + if (reg_field->ptr != next_virtual) + goto err; + next_virtual+= reg_field->pack_length_in_rec(); + } + else + { + first_virtual= reg_field->ptr; + next_virtual= first_virtual + reg_field->pack_length_in_rec(); + } + } + else // reg_field < next_stored. can happen if the i=0 field was virtual + { + if (next_virtual) + goto err; + first_virtual= first_stored; + next_virtual= next_stored; + first_stored= reg_field->ptr; + next_stored= first_stored + reg_field->pack_length_in_rec(); + } + if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD || attr.unireg_check == Field::TIMESTAMP_DN_FIELD) { @@ -2818,7 +2893,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, /* We want to store the value for the last bits */ swap_variables(uchar*, null_pos, mysql57_vcol_null_pos); swap_variables(uint, null_bit_pos, mysql57_vcol_null_bit_pos); - DBUG_ASSERT((null_pos + (null_bit_pos + 7) / 8) <= share->field[0]->ptr); + if ((null_pos + (null_bit_pos + 7) / 8) > share->field[0]->ptr) + goto err; } /* Fix key->name and key_part->field */ @@ -2846,7 +2922,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, hash_keypart->fieldnr= hash_field_used_no + 1; hash_field= share->field[hash_field_used_no]; hash_field->flags|= LONG_UNIQUE_HASH_FIELD;//Used in parse_vcol_defs - DBUG_ASSERT(hash_field->invisible == INVISIBLE_FULL); + if (hash_field->invisible != INVISIBLE_FULL || + hash_field->pack_length() != HA_HASH_FIELD_LENGTH) + goto err; keyinfo->flags|= HA_NOSAME; share->virtual_fields++; share->stored_fields--; @@ -2875,7 +2953,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, key_part= keyinfo->key_part; for (i=0 ; i < keyinfo->user_defined_key_parts ;i++) { - DBUG_ASSERT(key_part[i].fieldnr > 0); + if (key_part[i].fieldnr <= 0 || key_part[i].fieldnr > share->fields) + goto err; // Table field corresponding to the i'th key part. Field *table_field= share->field[key_part[i].fieldnr - 1]; @@ -2943,6 +3022,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, for (i= 0; i < first_keyinfo.user_defined_key_parts; i++) { uint fieldnr= keyinfo[0].key_part[i].fieldnr; + if (fieldnr <= 0 || fieldnr > share->fields) + goto err; if (share->field[fieldnr-1]->key_length() != keyinfo[0].key_part[i].length) { @@ -2990,6 +3071,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, { uint length_bytes= 0; uint fieldnr= keyinfo->key_part[i].fieldnr; + if (fieldnr <= 0 || fieldnr > share->fields) + goto err; field= share->field[fieldnr-1]; if (field->null_ptr) @@ -3067,7 +3150,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, share->default_values, (uint) key_part->offset, (uint) key_part->length); - if (!key_part->fieldnr) + if (key_part->fieldnr <= 0 || key_part->fieldnr > share->fields) goto err; field= key_part->field= share->field[key_part->fieldnr-1]; @@ -3219,7 +3302,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } else share->primary_key= MAX_KEY; - if (new_field_pack_flag <= 1) + if (new_field_pack_flag <= 1 && share->null_fields) { /* Old file format with default as not null */ uint null_length= (share->null_fields+7)/8; @@ -3232,8 +3315,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, /* Handle virtual expressions */ if (vcol_screen_length && share->frm_version >= FRM_VER_EXPRESSSIONS) { - uchar *vcol_screen_end= vcol_screen_pos + vcol_screen_length; - /* Skip header */ vcol_screen_pos+= FRM_VCOL_NEW_BASE_SIZE; share->vcol_defs.str+= FRM_VCOL_NEW_BASE_SIZE; @@ -3246,6 +3327,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, while (vcol_screen_pos < vcol_screen_end) { Virtual_column_info *vcol_info; + if (vcol_screen_end - vcol_screen_pos < FRM_VCOL_NEW_HEADER_SIZE) + goto err; + uint type= (uint) vcol_screen_pos[0]; uint field_nr= uint2korr(vcol_screen_pos+1); uint expr_length= uint2korr(vcol_screen_pos+3); @@ -3258,17 +3342,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (field_nr != UINT_MAX16) { - DBUG_ASSERT(field_nr < share->fields); + if (field_nr >= share->fields) + goto err; reg_field= share->field[field_nr]; } else { reg_field= 0; - DBUG_ASSERT(name_length); + if (!name_length || type != VCOL_CHECK_TABLE) + goto err; } vcol_screen_pos+= FRM_VCOL_NEW_HEADER_SIZE; vcol_info->set_vcol_type((enum_vcol_info_type) type); + if ((uint)(vcol_screen_end-vcol_screen_pos) < name_length+expr_length) + goto err; if (name_length) { vcol_info->name.str= strmake_root(&share->mem_root, @@ -3282,7 +3370,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, switch (type) { case VCOL_GENERATED_VIRTUAL: { - uint recpos; + if (reg_field->vcol_info) + goto err; reg_field->vcol_info= vcol_info; share->virtual_fields++; share->stored_fields--; @@ -3291,37 +3380,43 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (reg_field->flags & PART_KEY_FLAG) vcol_info->set_vcol_type(VCOL_GENERATED_VIRTUAL_INDEXED); /* Correct stored_rec_length as non stored fields are last */ - recpos= (uint) (reg_field->ptr - record); + uint recpos= (uint) (reg_field->ptr - record); if (share->stored_rec_length >= recpos) share->stored_rec_length= recpos-1; break; } case VCOL_GENERATED_STORED: vcol_info->stored_in_db= 1; - DBUG_ASSERT(!reg_field->vcol_info); + if (reg_field->vcol_info) + goto err; reg_field->vcol_info= vcol_info; share->virtual_fields++; break; case VCOL_DEFAULT: vcol_info->stored_in_db= 1; - DBUG_ASSERT(!reg_field->default_value); + if (reg_field->default_value) + goto err; reg_field->default_value= vcol_info; share->default_expressions++; break; case VCOL_CHECK_FIELD: - DBUG_ASSERT(!reg_field->check_constraint); + if (reg_field->check_constraint) + goto err; reg_field->check_constraint= vcol_info; share->field_check_constraints++; break; case VCOL_CHECK_TABLE: - *(table_check_constraints++)= vcol_info; + if ((uint)(table_check_constr - share->check_constraints) >= + share->table_check_constraints) + goto err; + *(table_check_constr++)= vcol_info; break; } } } - DBUG_ASSERT((uint) (table_check_constraints - share->check_constraints) == - (uint) (share->table_check_constraints - - share->field_check_constraints)); + if (table_check_constr - share->check_constraints != + (int)share->table_check_constraints - (int)share->field_check_constraints) + goto err; if (options.str) { @@ -3374,6 +3469,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, share->can_cmp_whole_record= (share->blob_fields == 0 && share->varchar_fields == 0); + data_start= share->default_values; + data_end= data_start + share->reclength; + if (share->null_field_first) + data_start+= share->null_bytes; + else + data_end-= share->null_bytes; + + if (data_end < data_start || + (first_virtual && first_virtual != next_stored) || + first_stored < data_start || + (next_virtual ? next_virtual : next_stored) > data_end) + goto err; + share->column_bitmap_size= bitmap_buffer_size(share->fields); bitmap_count= 1; @@ -4823,19 +4931,20 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error, } /* open_table_error */ - /* - ** fix a str_type to a array type - ** typeparts separated with some char. differents types are separated - ** with a '\0' - */ +/* + fix a str_type to a array type + typeparts separated with some char. differents types are separated + with a '\0' +*/ static bool -fix_type_pointers(const char ***typelib_value_names, +fix_type_pointers(const char ***typelib_value_names, const char **names_end, uint **typelib_value_lengths, TYPELIB *point_to_type, uint types, char *ptr, size_t length) { const char *end= ptr + length; + names_end--; // simplify the check below, reserve place for 0 at the end while (types--) { @@ -4867,7 +4976,7 @@ fix_type_pointers(const char ***typelib_value_names, { // Now scan the next value+sep pair char *vend= (char*) memchr(ptr, sep, end - ptr); - if (!vend) + if (!vend || *typelib_value_names >= names_end) return true; // Bad format *((*typelib_value_names)++)= ptr; *((*typelib_value_lengths)++)= (uint) (vend - ptr); diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 1ee1f07108a..069777ce5f0 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -947,14 +947,21 @@ uint32 ha_archive::max_row_length(const uchar *record) unsigned int ha_archive::pack_row(const uchar *record, azio_stream *writer) { uchar *ptr; + uint32 max_len; my_ptrdiff_t const rec_offset= record - table->record[0]; DBUG_ENTER("ha_archive::pack_row"); - if (fix_rec_buff(max_row_length(record))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */ + max_len= max_row_length(record); if (writer->version == 1) + { + if (fix_rec_buff(max_len)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */ DBUG_RETURN(pack_row_v1(record)); + } + + if (fix_rec_buff(max_len + ARCHIVE_ROW_HEADER_SIZE)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* Copy null bits */ memcpy(record_buffer->buffer+ARCHIVE_ROW_HEADER_SIZE, @@ -1582,6 +1589,46 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) while (!(rc= get_row(&archive, table->record[0]))) { + /* + If the source is version 3, unpack_row() stores blob data in + record_buffer. Since pack_row() also uses record_buffer for + packing, we must copy blob data out first to avoid corruption. + Version 2 already stores blobs in the 'buffer' member. + */ + if (archive.version >= 3) + { + uint *blob_ptr, *blob_end; + size_t total_blob_length= 0; + for (blob_ptr= table->s->blob_field, + blob_end= blob_ptr + table->s->blob_fields; + blob_ptr != blob_end; blob_ptr++) + { + Field_blob *blob= (Field_blob*) table->field[*blob_ptr]; + if (!blob->is_null()) + total_blob_length+= blob->get_length(); + } + if (buffer.alloc(total_blob_length)) + { + rc= HA_ERR_OUT_OF_MEM; + break; + } + char *pos= (char*) buffer.ptr(); + for (blob_ptr= table->s->blob_field, + blob_end= blob_ptr + table->s->blob_fields; + blob_ptr != blob_end; blob_ptr++) + { + Field_blob *blob= (Field_blob*) table->field[*blob_ptr]; + if (blob->is_null()) + continue; + uint32 length= blob->get_length(); + if (length) + { + memcpy(pos, blob->get_ptr(), length); + blob->set_ptr(length, (uchar*) pos); + pos+= length; + } + } + } real_write_row(table->record[0], &writer); /* Long term it should be possible to optimize this so that @@ -1601,6 +1648,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) tmp_restore_column_map(&table->read_set, org_bitmap); share->rows_recorded= (ha_rows)writer.rows; + buffer.free(); } DBUG_PRINT("info", ("recovered %llu archive rows", diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 01b3df4b1a0..e9af2c6edad 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -29,14 +29,14 @@ SET(CONNECT_SOURCES ha_connect.cc connect.cc user_connect.cc mycat.cc fmdlex.c osutil.c rcmsg.c rcmsg.h array.cpp blkfil.cpp colblk.cpp csort.cpp -filamap.cpp filamdbf.cpp filamfix.cpp filamgz.cpp filamtxt.cpp filter.cpp +filamap.cpp filamdbf.cpp filamfix.cpp filamgz.cpp filamtxt.cpp filechk.cpp filter.cpp json.cpp jsonudf.cpp maputil.cpp myconn.cpp myutil.cpp plgdbutl.cpp plugutil.cpp reldef.cpp tabcol.cpp tabdos.cpp tabext.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp tabmysql.cpp taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h -engmsg.h filamap.h filamdbf.h filamfix.h filamgz.h filamtxt.h +engmsg.h filamap.h filamdbf.h filamfix.h filamgz.h filamtxt.h filechk.h filter.h global.h ha_connect.h inihandl.h json.h jsonudf.h maputil.h msgid.h mycat.h myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h tabcol.h tabdos.h tabext.h tabfix.h tabfmt.h tabjson.h tabmul.h diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index c12eefb5b67..41c721f6227 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -16,6 +16,7 @@ #include #include "bsonudf.h" +#include "filechk.h" #if defined(UNIX) || defined(UNIV_LINUX) #define _O_RDONLY O_RDONLY @@ -4478,6 +4479,16 @@ char *bson_file(UDF_INIT *initid, UDF_ARGS *args, char *result, PlugSubSet(g->Sarea, g->Sarea_Size); fn = MakePSZ(g, args, 0); + if (!fn) { + PUSH_WARNING("Missing file name"); + *is_null = 1; + return NULL; + } else if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + *is_null = 1; + return NULL; + } + if (args->arg_count > 1) { int pretty = 3, pty = 3; size_t len; @@ -4629,7 +4640,10 @@ char *bfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endswitch arg_type if (fn) { - if (!bnx.Serialize(g, jvp, fn, pretty)) + if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + fn = NULL; + } else if (!bnx.Serialize(g, jvp, fn, pretty)) PUSH_WARNING(g->Message); } else PUSH_WARNING("Missing file name"); @@ -6065,6 +6079,16 @@ char *bbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result, fn = MakePSZ(g, args, 0); + if (!fn) { + PUSH_WARNING("Missing file name"); + *error = 1; + goto fin; + } else if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + *error = 1; + goto fin; + } + for (unsigned int i = 1; i < args->arg_count; i++) if (args->arg_type[i] == INT_RESULT && *(longlong*)args->args[i] < 4) { pretty = (int) * (longlong*)args->args[i]; diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index ee65e0cf5db..d0972ac131f 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -246,7 +246,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info) bool bad, mul; PCSZ target, pwd; DBFHEADER mainhead, *hp = NULL; - DESCRIPTOR thisfield, *tfp; + DESCRIPTOR thisfield, *tfp= &thisfield; FILE *infile = NULL; UNZIPUTL *zutp = NULL; PQRYRES qrp; @@ -308,7 +308,6 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info) return NULL; } // endif dbfhead - tfp = &thisfield; } // endif zipped /************************************************************************/ diff --git a/storage/connect/filechk.cpp b/storage/connect/filechk.cpp new file mode 100644 index 00000000000..03e88633e99 --- /dev/null +++ b/storage/connect/filechk.cpp @@ -0,0 +1,41 @@ +/* Copyright (C) MariaDB Corporation Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include +#include +#include +#include "filechk.h" + +/* + @return true if the current user may access path. +*/ +bool connect_can_access_file(const char *path) +{ + char real_path[FN_REFLEN]; + + if (!path) + return false; /* callers must check for NULL before calling */ + + if (check_global_access(current_thd, FILE_ACL, true)) + return false; + + /* MY_SAFE_PATH returns NULL on overflow; fail closed rather than validate a truncated path */ + if (!fn_format(real_path, path, mysql_real_data_home, "", + MY_RELATIVE_PATH | MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | MY_SAFE_PATH)) + return false; + + return is_secure_file_path(real_path); +} diff --git a/storage/connect/filechk.h b/storage/connect/filechk.h new file mode 100644 index 00000000000..75ab7eda09e --- /dev/null +++ b/storage/connect/filechk.h @@ -0,0 +1,20 @@ +/* Copyright (C) MariaDB Corporation Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* File access checks for CONNECT file UDFs */ +#pragma once +bool connect_can_access_file(const char *path); + diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index cc916feaeaa..e11cb2a466b 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -15,6 +15,7 @@ #include #include "jsonudf.h" +#include "filechk.h" #if defined(UNIX) || defined(UNIV_LINUX) #define _O_RDONLY O_RDONLY @@ -4562,6 +4563,16 @@ char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result, PlugSubSet(g->Sarea, g->Sarea_Size); fn = MakePSZ(g, args, 0); + if (!fn) { + PUSH_WARNING("Missing file name"); + *is_null = 1; + return NULL; + } else if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + *is_null = 1; + return NULL; + } + if (args->arg_count > 1) { int pretty = 3, pty = 3; size_t len; @@ -4715,7 +4726,10 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endswitch arg_type if (fn) { - if (!Serialize(g, jvp->GetJson(), fn, pretty)) + if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + fn = NULL; + } else if (!Serialize(g, jvp->GetJson(), fn, pretty)) PUSH_WARNING(g->Message); } else PUSH_WARNING("Missing file name"); @@ -5767,8 +5781,8 @@ my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message) if (args->arg_count < 1 || args->arg_count > 4) { strcpy(message, "This function only accepts 1 to 4 arguments"); return true; - } else if (args->arg_type[0] != STRING_RESULT || !args->args[0]) { - strcpy(message, "First argument must be a constant string (file name)"); + } else if (args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a string (file name)"); return true; } // endifs @@ -5786,7 +5800,10 @@ my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message) initid->maybe_null = 1; CalcLen(args, false, reslen, memlen); - fl = GetFileLength(args->args[0]); + if (args->args[0]) + fl = GetFileLength(args->args[0]); + else + fl = 100; // What can be done here? reslen += fl; more += fl * M; //memlen += more; @@ -5811,6 +5828,16 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result, g->Xchk = NULL; fn = MakePSZ(g, args, 0); + if (!fn) { + PUSH_WARNING("Missing file name"); + *error = 1; + goto fin; + } else if (!connect_can_access_file(fn)) { + PUSH_WARNING("Access denied: FILE privilege or secure_file_priv violation"); + *error = 1; + goto fin; + } + for (unsigned int i = 1; i < args->arg_count; i++) if (args->arg_type[i] == INT_RESULT && *(longlong*)args->args[i] < 4) { pretty = (int) * (longlong*)args->args[i]; diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result index f9b9b7e87d2..8f5341bbcce 100644 --- a/storage/connect/mysql-test/connect/r/drop-open-error.result +++ b/storage/connect/mysql-test/connect/r/drop-open-error.result @@ -5,11 +5,3 @@ drop table mdev9949; Warnings: Warning 1017 Can't find file: 'DATADIR/test/mdev9949.dos' (errno: 2 "No such file or directory") drop table t1; -select @@secure_file_priv 'must be NULL'; -must be NULL -NULL -create table t1 (a char(16)) engine=myisam; -insert into t1 values('Hello World!'); -create table t2 engine=connect file_name='foo/bar.txt' as select * from t1; -ERROR HY000: Got error 174 'Open(a+b) error 2 on foo/bar.txt: No such file or directory' from CONNECT -drop table t1; diff --git a/storage/connect/mysql-test/connect/r/fix.result b/storage/connect/mysql-test/connect/r/fix.result index d6cdad0373b..2b5f2595da2 100644 --- a/storage/connect/mysql-test/connect/r/fix.result +++ b/storage/connect/mysql-test/connect/r/fix.result @@ -129,3 +129,13 @@ Sam Chicago 1979-11-22 2007-10-10 James Dallas 1992-05-13 2009-12-14 Bill Boston 1986-09-11 2008-02-10 DROP TABLE t1; +# +# MDEV-40637 CONNECT crashes on double(255,50) in DOS table +# +create table t (x double(255,30)) engine=connect table_type='dos' file_name='t.dos'; +insert into t values (1e50); +select * from t; +x +1000000000000000000000000000000.000000000000000000000000000000 +drop table t; +# End of 10.6 tests diff --git a/storage/connect/mysql-test/connect/r/json_bson_file_priv.result b/storage/connect/mysql-test/connect/r/json_bson_file_priv.result new file mode 100644 index 00000000000..34cbf8c972b --- /dev/null +++ b/storage/connect/mysql-test/connect/r/json_bson_file_priv.result @@ -0,0 +1,156 @@ +# +# Test FILE privilege and secure_file_priv enforcement for JSON/BSON file UDFs +# +# Privileged user: path inside secure_file_priv MYSQL_TMP_DIR +select json_file('MYSQL_TMP_DIR/bib0.json', 0) IS NOT NULL AS ok; +ok +1 +select bson_file('MYSQL_TMP_DIR/biblio.json', 0) IS NOT NULL AS ok; +ok +1 +Warnings: +Warning 1105 File pretty format doesn't match the specified pretty value +select jfile_make('{"test":1}', 'MYSQL_TMP_DIR/out.json', 0) IS NOT NULL AS ok; +ok +1 +select bfile_make('{"test":1}', 'MYSQL_TMP_DIR/out.json', 0) IS NOT NULL AS ok; +ok +1 +select jbin_file('MYSQL_TMP_DIR/bib0.json') IS NOT NULL AS ok; +ok +1 +select bbin_file('MYSQL_TMP_DIR/biblio.json') IS NOT NULL AS ok; +ok +1 +# Privileged user: path outside secure_file_priv +select json_file('DATADIR/bib0.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bson_file('DATADIR/biblio.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select jfile_make('{"test":1}', 'DATADIR/out.json', 0) IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bfile_make('{"test":1}', 'DATADIR/out.json', 0) IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select jbin_file('DATADIR/bib0.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bbin_file('DATADIR/biblio.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +# NULL argument: no "access denied", UDF reports its own error +select json_file(NULL) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +select bson_file(NULL) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +select jfile_make('{"test":1}', NULL, 0) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +select bfile_make('{"test":1}', NULL, 0) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +select jbin_file(NULL) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +select bbin_file(NULL) IS NULL AS ok; +ok +1 +Warnings: +Warning 1105 Missing file name +# Privileged user: relative path resolving outside secure_file_priv +select json_file('../../bib0.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bson_file('../../biblio.json') IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +# Overlong filename: MY_SAFE_PATH rejects it, fail closed +select json_file(concat('MYSQL_TMP_DIR/', repeat('x', 512))) IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bson_file(concat('MYSQL_TMP_DIR/', repeat('x', 512))) IS NULL AS denied; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +# Non-constant filename expression (args->args[0] is NULL at init time) +set @fname = 'MYSQL_TMP_DIR/bib0.json'; +select jbin_file(@fname) IS NOT NULL AS ok; +ok +1 +set @fname = 'MYSQL_TMP_DIR/biblio.json'; +select bbin_file(@fname) IS NOT NULL AS ok; +ok +1 +# User without FILE privilege +create user unprivileged@localhost; +grant select ON *.* TO unprivileged@localhost; +connect unprivileged,localhost,unprivileged,,; +connection unprivileged; +# inside secure_file_priv: denied without FILE privilege +select json_file('MYSQL_TMP_DIR/bib0.json') IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bson_file('MYSQL_TMP_DIR/biblio.json') IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select jfile_make('{"test":1}', 'MYSQL_TMP_DIR/out.json', 0) IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bfile_make('{"test":1}', 'MYSQL_TMP_DIR/out.json', 0) IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select jbin_file('MYSQL_TMP_DIR/bib0.json') IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +select bbin_file('MYSQL_TMP_DIR/biblio.json') IS NULL AS denied;; +denied +1 +Warnings: +Warning 1105 Access denied: FILE privilege or secure_file_priv violation +disconnect unprivileged; +connection default; +drop user unprivileged@localhost; diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.opt b/storage/connect/mysql-test/connect/t/drop-open-error.opt deleted file mode 100644 index 22520f0aa99..00000000000 --- a/storage/connect/mysql-test/connect/t/drop-open-error.opt +++ /dev/null @@ -1 +0,0 @@ ---secure-file-priv="" diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.test b/storage/connect/mysql-test/connect/t/drop-open-error.test index dd286c96466..97d938e4310 100644 --- a/storage/connect/mysql-test/connect/t/drop-open-error.test +++ b/storage/connect/mysql-test/connect/t/drop-open-error.test @@ -18,14 +18,3 @@ copy_file $MTR_SUITE_DIR/std_data/mdev9949.frm $datadir/test/mdev9949.frm; --replace_result $MARIADB_DATADIR DATADIR/ './' 'DATADIR/' drop table mdev9949; drop table t1; - -# -# MDEV-7935 CREATE TABLE ... AS SELECT ... can cause a Server crash (Assertion `0' in Protocol::end_statement) -# -select @@secure_file_priv 'must be NULL'; # otherwise foo/bar.txt won't be allowed -create table t1 (a char(16)) engine=myisam; -insert into t1 values('Hello World!'); -replace_regex @on .*/foo/@on foo/@; -error ER_GET_ERRMSG; -create table t2 engine=connect file_name='foo/bar.txt' as select * from t1; -drop table t1; diff --git a/storage/connect/mysql-test/connect/t/fix.test b/storage/connect/mysql-test/connect/t/fix.test index f05abbb9b92..a38fe5623a6 100644 --- a/storage/connect/mysql-test/connect/t/fix.test +++ b/storage/connect/mysql-test/connect/t/fix.test @@ -106,3 +106,14 @@ DROP TABLE t1; --remove_file $MYSQLD_DATADIR/test/dept.dat --remove_file $MYSQLD_DATADIR/test/boys.txt --remove_file $MYSQLD_DATADIR/test/boyswin.txt + +--echo # +--echo # MDEV-40637 CONNECT crashes on double(255,50) in DOS table +--echo # +create table t (x double(255,30)) engine=connect table_type='dos' file_name='t.dos'; +insert into t values (1e50); +select * from t; +drop table t; +--remove_file $MYSQLD_DATADIR/test/t.dos + +--echo # End of 10.6 tests diff --git a/storage/connect/mysql-test/connect/t/json_bson_file_priv.opt b/storage/connect/mysql-test/connect/t/json_bson_file_priv.opt new file mode 100644 index 00000000000..e9a43a5584d --- /dev/null +++ b/storage/connect/mysql-test/connect/t/json_bson_file_priv.opt @@ -0,0 +1 @@ +--secure_file_priv=$MYSQL_TMP_DIR diff --git a/storage/connect/mysql-test/connect/t/json_bson_file_priv.test b/storage/connect/mysql-test/connect/t/json_bson_file_priv.test new file mode 100644 index 00000000000..04c91184a94 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/json_bson_file_priv.test @@ -0,0 +1,100 @@ +--source include/not_embedded.inc +--source json_udf.inc +--source bson_udf.inc + +let $MYSQLD_DATADIR = `select @@datadir`; + +--copy_file $MTR_SUITE_DIR/std_data/bib0.json $MYSQL_TMP_DIR/bib0.json +--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQL_TMP_DIR/biblio.json + +--echo # +--echo # Test FILE privilege and secure_file_priv enforcement for JSON/BSON file UDFs +--echo # + +--echo # Privileged user: path inside secure_file_priv MYSQL_TMP_DIR +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select json_file('$MYSQL_TMP_DIR/bib0.json', 0) IS NOT NULL AS ok +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bson_file('$MYSQL_TMP_DIR/biblio.json', 0) IS NOT NULL AS ok +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select jfile_make('{"test":1}', '$MYSQL_TMP_DIR/out.json', 0) IS NOT NULL AS ok +--remove_file $MYSQL_TMP_DIR/out.json +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bfile_make('{"test":1}', '$MYSQL_TMP_DIR/out.json', 0) IS NOT NULL AS ok +--remove_file $MYSQL_TMP_DIR/out.json +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select jbin_file('$MYSQL_TMP_DIR/bib0.json') IS NOT NULL AS ok +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bbin_file('$MYSQL_TMP_DIR/biblio.json') IS NOT NULL AS ok + +--echo # Privileged user: path outside secure_file_priv +--replace_result $MYSQLD_DATADIR DATADIR +--eval select json_file('$MYSQLD_DATADIR/bib0.json') IS NULL AS denied +--replace_result $MYSQLD_DATADIR DATADIR +--eval select bson_file('$MYSQLD_DATADIR/biblio.json') IS NULL AS denied +--replace_result $MYSQLD_DATADIR DATADIR +--eval select jfile_make('{"test":1}', '$MYSQLD_DATADIR/out.json', 0) IS NULL AS denied +--replace_result $MYSQLD_DATADIR DATADIR +--eval select bfile_make('{"test":1}', '$MYSQLD_DATADIR/out.json', 0) IS NULL AS denied +--replace_result $MYSQLD_DATADIR DATADIR +--eval select jbin_file('$MYSQLD_DATADIR/bib0.json') IS NULL AS denied +--replace_result $MYSQLD_DATADIR DATADIR +--eval select bbin_file('$MYSQLD_DATADIR/biblio.json') IS NULL AS denied + +--echo # NULL argument: no "access denied", UDF reports its own error +select json_file(NULL) IS NULL AS ok; +select bson_file(NULL) IS NULL AS ok; +select jfile_make('{"test":1}', NULL, 0) IS NULL AS ok; +select bfile_make('{"test":1}', NULL, 0) IS NULL AS ok; +select jbin_file(NULL) IS NULL AS ok; +select bbin_file(NULL) IS NULL AS ok; + +--echo # Privileged user: relative path resolving outside secure_file_priv +select json_file('../../bib0.json') IS NULL AS denied; +select bson_file('../../biblio.json') IS NULL AS denied; + +--echo # Overlong filename: MY_SAFE_PATH rejects it, fail closed +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select json_file(concat('$MYSQL_TMP_DIR/', repeat('x', 512))) IS NULL AS denied +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bson_file(concat('$MYSQL_TMP_DIR/', repeat('x', 512))) IS NULL AS denied + +--echo # Non-constant filename expression (args->args[0] is NULL at init time) +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval set @fname = '$MYSQL_TMP_DIR/bib0.json' +select jbin_file(@fname) IS NOT NULL AS ok; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval set @fname = '$MYSQL_TMP_DIR/biblio.json' +select bbin_file(@fname) IS NOT NULL AS ok; + +--echo # User without FILE privilege +create user unprivileged@localhost; +grant select ON *.* TO unprivileged@localhost; + +--connect(unprivileged,localhost,unprivileged,,) +--connection unprivileged + +--echo # inside secure_file_priv: denied without FILE privilege +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select json_file('$MYSQL_TMP_DIR/bib0.json') IS NULL AS denied; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bson_file('$MYSQL_TMP_DIR/biblio.json') IS NULL AS denied; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select jfile_make('{"test":1}', '$MYSQL_TMP_DIR/out.json', 0) IS NULL AS denied; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bfile_make('{"test":1}', '$MYSQL_TMP_DIR/out.json', 0) IS NULL AS denied; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select jbin_file('$MYSQL_TMP_DIR/bib0.json') IS NULL AS denied; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +--eval select bbin_file('$MYSQL_TMP_DIR/biblio.json') IS NULL AS denied; + +--disconnect unprivileged +--connection default + +--remove_file $MYSQL_TMP_DIR/bib0.json +--remove_file $MYSQL_TMP_DIR/biblio.json + +drop user unprivileged@localhost; + +--source json_udf2.inc +--source bson_udf2.inc diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index b648aa1c956..7dcc8d55394 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -746,7 +746,7 @@ bool TYPVAL::SetValue_char(const char *p, int n) for (; n > 0 && *p == ' '; p++) n--; - memcpy(buf, p, MY_MIN(n, 31)); + memcpy(buf, p, n= MY_MIN(n, 31)); buf[n] = '\0'; Tval = atof(buf); diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 43fc7d2bda0..de195cae54f 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. + Copyright (c) 2026, MariaDB plc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -646,7 +647,8 @@ int ha_tina::chain_append() if (chain_alloced) { if ((chain= (tina_set *) my_realloc(csv_key_memory_tina_set, - (uchar*)chain, chain_size, + (uchar*)chain, + chain_size * sizeof(tina_set), MYF(MY_WME))) == NULL) return -1; } diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 489e81121a4..cdeff50b085 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -1333,6 +1333,9 @@ err: @retval # How many chars was removed */ +#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 && _MSC_VER < 1951 +#pragma optimize("g", off) +#endif static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag, uchar *keypos, uchar *lastkey, uchar *page_end, my_off_t *next_block, @@ -1473,6 +1476,9 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag, DBUG_RETURN((uint) s_length); } /* remove_key */ +#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 && _MSC_VER < 1951 +#pragma optimize("", on) +#endif /**************************************************************************** Logging of redos diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 12f39595fa5..c6731655069 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -4313,18 +4313,15 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint open_options) if (error) DBUG_RETURN(error); - if (!(open_options & HA_OPEN_FOR_REPAIR)) { - error = open_table(name); - if (error) - DBUG_RETURN(error); + error = open_table(name); + if (error && !(open_options & HA_OPEN_FOR_REPAIR)) + goto error_exit; - error = wrapper_open_indexes(name); - if (error) { - grn_obj_unlink(ctx, grn_table); - grn_table = NULL; - DBUG_RETURN(error); - } - } + error = wrapper_open_indexes(name); + if (error && !(open_options & HA_OPEN_FOR_REPAIR)) + goto error_exit; + + error = 0; mrn_init_alloc_root(&mem_root, 1024, 0, MYF(0)); wrap_key_info = mrn_create_key_info_for_table(share, table, &error); @@ -4412,6 +4409,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint open_options) } } +error_exit: if (error) { grn_obj_unlink(ctx, grn_table); @@ -4684,37 +4682,35 @@ int ha_mroonga::storage_open(const char *name, int mode, uint open_options) DBUG_RETURN(error); } + error = storage_open_indexes(name); + if (error && !(open_options & HA_OPEN_FOR_REPAIR)) { + storage_close_columns(); + grn_obj_unlink(ctx, grn_table); + grn_table = NULL; + DBUG_RETURN(error); + } + + storage_set_keys_in_use(); + if (!(open_options & HA_OPEN_FOR_REPAIR)) { - error = storage_open_indexes(name); - if (error) { - storage_close_columns(); - grn_obj_unlink(ctx, grn_table); - grn_table = NULL; - DBUG_RETURN(error); - } - - storage_set_keys_in_use(); - - { - mrn::Lock lock(&mrn_operations_mutex); - mrn::PathMapper mapper(name); - const char *table_name = mapper.table_name(); - size_t table_name_size = strlen(table_name); - if (db->is_broken_table(table_name, table_name_size)) { - GRN_LOG(ctx, GRN_LOG_NOTICE, - "Auto repair is started: <%s>", - name); - error = operations_->repair(table_name, table_name_size); + mrn::Lock lock(&mrn_operations_mutex); + mrn::PathMapper mapper(name); + const char *table_name = mapper.table_name(); + size_t table_name_size = strlen(table_name); + if (db->is_broken_table(table_name, table_name_size)) { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "Auto repair is started: <%s>", + name); + error = operations_->repair(table_name, table_name_size); + if (!error) + db->mark_table_repaired(table_name, table_name_size); + if (!share->disable_keys) { if (!error) - db->mark_table_repaired(table_name, table_name_size); - if (!share->disable_keys) { - if (!error) - error = storage_reindex(); - } - GRN_LOG(ctx, GRN_LOG_NOTICE, - "Auto repair is done: <%s>: %s", - name, error == 0 ? "success" : "failure"); + error = storage_reindex(); } + GRN_LOG(ctx, GRN_LOG_NOTICE, + "Auto repair is done: <%s>: %s", + name, error == 0 ? "success" : "failure"); } } @@ -5258,7 +5254,7 @@ void ha_mroonga::storage_set_keys_in_use() if (i == table_share->primary_key) { continue; } - if (!grn_index_tables[i]) { + if (grn_index_tables && !grn_index_tables[i]) { /* disabled */ table_share->keys_in_use.clear_bit(i); DBUG_PRINT("info", ("mroonga: key %u disabled", i)); diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/check_table_broken.result b/storage/mroonga/mysql-test/mroonga/storage/r/check_table_broken.result index 4926a72a77a..af85e783cd5 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/check_table_broken.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/check_table_broken.result @@ -9,10 +9,17 @@ INSERT INTO diaries VALUES ('Hello'); FLUSH TABLES; CHECK TABLE diaries; Table Op Msg_type Msg_text +check_test.diaries check Error system call error: No such file or directory: failed to open path: check_test.diaries check error Corrupt REPAIR TABLE diaries; Table Op Msg_type Msg_text +check_test.diaries repair Error system call error: No such file or directory: failed to open path: check_test.diaries repair status OK +SELECT * +FROM diaries +WHERE MATCH(title) AGAINST('+Hello' IN BOOLEAN MODE); +title +Hello DROP TABLE diaries; DROP DATABASE check_test; USE test; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/check_table_innodb.result b/storage/mroonga/mysql-test/mroonga/storage/r/check_table_innodb.result new file mode 100644 index 00000000000..628a33af7f9 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/check_table_innodb.result @@ -0,0 +1,13 @@ +# +# MDEV-39556 SIGSEGV in ha_mroonga::storage_set_keys_in_use on SELECT +# +CREATE TABLE t (c INT KEY,c2 GEOMETRY NOT NULL,SPATIAL INDEX idx_sp (c2)) ENGINE=InnoDB; +ALTER TABLE t ENGINE=Mroonga; +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +SELECT COUNT(*) > 0 AS r FROM information_schema.STATISTICS; +r +1 +DROP TABLE t; +# End of 10.6 tests diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/repair_table_no_index_file.result b/storage/mroonga/mysql-test/mroonga/storage/r/repair_table_no_index_file.result index 24d427ed2ab..f58b3916eaf 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/repair_table_no_index_file.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/repair_table_no_index_file.result @@ -17,6 +17,7 @@ SELECT * FROM diaries WHERE MATCH(body) AGAINST("+starting" IN BOOLEAN MODE); ERROR HY000: system call error: No such file or directory: failed to open path: REPAIR TABLE diaries; Table Op Msg_type Msg_text +repair_test.diaries repair Error system call error: No such file or directory: failed to open path: repair_test.diaries repair status OK SELECT * FROM diaries; id title body diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/check_table_broken.test b/storage/mroonga/mysql-test/mroonga/storage/t/check_table_broken.test index d438a912ae2..d4666e60055 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/check_table_broken.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/check_table_broken.test @@ -31,12 +31,16 @@ CREATE TABLE diaries ( INSERT INTO diaries VALUES ('Hello'); --remove_file $MYSQLD_DATADIR/check_test.mrn.000010C - FLUSH TABLES; CHECK TABLE diaries; REPAIR TABLE diaries; + +SELECT * + FROM diaries + WHERE MATCH(title) AGAINST('+Hello' IN BOOLEAN MODE); + DROP TABLE diaries; DROP DATABASE check_test; diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/check_table_innodb.test b/storage/mroonga/mysql-test/mroonga/storage/t/check_table_innodb.test new file mode 100644 index 00000000000..e34d30ec29d --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/check_table_innodb.test @@ -0,0 +1,16 @@ +--source include/have_innodb.inc +--source ../../include/mroonga/have_mroonga.inc + +--echo # +--echo # MDEV-39556 SIGSEGV in ha_mroonga::storage_set_keys_in_use on SELECT +--echo # + +CREATE TABLE t (c INT KEY,c2 GEOMETRY NOT NULL,SPATIAL INDEX idx_sp (c2)) ENGINE=InnoDB; + +ALTER TABLE t ENGINE=Mroonga; +CHECK TABLE t; +SELECT COUNT(*) > 0 AS r FROM information_schema.STATISTICS; + +DROP TABLE t; + +--echo # End of 10.6 tests diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/repair_table_no_index_file.test b/storage/mroonga/mysql-test/mroonga/storage/t/repair_table_no_index_file.test index 0f04bd3e423..63624a9d56e 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/repair_table_no_index_file.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/repair_table_no_index_file.test @@ -43,6 +43,7 @@ FLUSH TABLES; --error ER_CANT_OPEN_FILE SELECT * FROM diaries WHERE MATCH(body) AGAINST("+starting" IN BOOLEAN MODE); +--replace_result "[io][open] " "" REPAIR TABLE diaries; SELECT * FROM diaries; diff --git a/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_files.result b/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_files.result index 8258a03bf42..98de2e89518 100644 --- a/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_files.result +++ b/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_files.result @@ -17,6 +17,7 @@ SELECT * FROM diaries WHERE MATCH(body) AGAINST("starting"); ERROR HY000: mroonga: failed to open table: REPAIR TABLE diaries; Table Op Msg_type Msg_text +repair_test.diaries repair Error mroonga: failed to open table: repair_test.diaries repair status OK SELECT * FROM diaries; id title body diff --git a/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_index_file.result b/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_index_file.result index cca7aee95de..271c086c4b3 100644 --- a/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_index_file.result +++ b/storage/mroonga/mysql-test/mroonga/wrapper/r/repair_table_no_index_file.result @@ -17,6 +17,7 @@ SELECT * FROM diaries WHERE MATCH(body) AGAINST("starting"); ERROR HY000: system call error: No such file or directory: failed to open path: REPAIR TABLE diaries; Table Op Msg_type Msg_text +repair_test.diaries repair Error system call error: No such file or directory: failed to open path: repair_test.diaries repair status OK SELECT * FROM diaries; id title body diff --git a/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test b/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test index 2fefadc254d..5061a268d8a 100644 --- a/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test +++ b/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test @@ -44,6 +44,7 @@ FLUSH TABLES; --error ER_CANT_OPEN_FILE SELECT * FROM diaries WHERE MATCH(body) AGAINST("starting"); +--replace_result "[io][open] " "" REPAIR TABLE diaries; SELECT * FROM diaries; diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c index 62409a15a46..aa9196dc0a4 100644 --- a/storage/myisam/mi_delete.c +++ b/storage/myisam/mi_delete.c @@ -767,7 +767,7 @@ err: returns how many chars was removed or 0 on error */ -#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 +#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 && _MSC_VER < 1951 #pragma optimize("g", off) #endif @@ -896,6 +896,6 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag, DBUG_RETURN((uint) s_length); } /* remove_key */ -#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 +#if defined(_MSC_VER) && defined(_M_X64) && _MSC_VER >= 1930 && _MSC_VER < 1951 #pragma optimize("",on) #endif diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index 195a646da35..1d867e44975 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -3298,7 +3298,7 @@ pfs_get_thread_file_name_locker_v1(PSI_file_locker_state *state, wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; - wait->m_object_instance_addr= NULL; + wait->m_object_instance_addr= 0; wait->m_weak_file= NULL; wait->m_weak_version= 0; wait->m_event_id= pfs_thread->m_event_id++; @@ -3378,7 +3378,7 @@ pfs_get_thread_file_stream_locker_v1(PSI_file_locker_state *state, wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; - wait->m_object_instance_addr= pfs_file; + wait->m_object_instance_addr= pfs_file->m_identity; wait->m_weak_file= pfs_file; wait->m_weak_version= pfs_file->get_version(); wait->m_event_id= pfs_thread->m_event_id++; @@ -3487,7 +3487,7 @@ pfs_get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; - wait->m_object_instance_addr= pfs_file; + wait->m_object_instance_addr= pfs_file->m_identity; wait->m_weak_file= pfs_file; wait->m_weak_version= pfs_file->get_version(); wait->m_event_id= pfs_thread->m_event_id++; @@ -4667,7 +4667,7 @@ void pfs_end_file_wait_v1(PSI_file_locker *locker, wait->m_timer_end= timer_end; wait->m_number_of_bytes= bytes; wait->m_end_event_id= thread->m_event_id; - wait->m_object_instance_addr= file; + wait->m_object_instance_addr= (file ? file->m_identity : 0); wait->m_weak_file= file; wait->m_weak_version= (file ? file->get_version() : 0); diff --git a/storage/perfschema/pfs.h b/storage/perfschema/pfs.h index 6e0cf258c91..b73e79498a9 100644 --- a/storage/perfschema/pfs.h +++ b/storage/perfschema/pfs.h @@ -23,11 +23,15 @@ #ifndef PFS_H #define PFS_H +#include + /** @file storage/perfschema/pfs.h Performance schema instrumentation (declarations). */ +typedef std::uint64_t pfs_identity; + #define HAVE_PSI_1 #include @@ -60,4 +64,3 @@ extern bool THR_PFS_initialized; #define PSI_COUNT_VOLATILITY 2 #endif - diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc index 2a877836649..88038e947e1 100644 --- a/storage/perfschema/pfs_account.cc +++ b/storage/perfschema/pfs_account.cc @@ -180,7 +180,7 @@ search: lf_hash_search_unpin(pins); - pfs= global_account_container.allocate(& dirty_state); + pfs= global_account_container.allocate(& dirty_state, NULL); if (pfs != NULL) { pfs->m_key= key; diff --git a/storage/perfschema/pfs_buffer_container.cc b/storage/perfschema/pfs_buffer_container.cc index 04f6f5219a3..4b96366c4a9 100644 --- a/storage/perfschema/pfs_buffer_container.cc +++ b/storage/perfschema/pfs_buffer_container.cc @@ -29,6 +29,26 @@ #include "pfs_buffer_container.h" #include "pfs_builtin_memory.h" +pfs_identity make_identity(pfs_container_id container_id, pfs_page_id page_id, + pfs_object_id object_id, + pfs_dirty_state *dirty_state) { + /* See pfs_lock, the version number is stored in the high 30 bits. */ + uint32_t version_32 = (dirty_state->m_version_state & VERSION_MASK) >> 2; + /* Isolate 16 least significant bits from the version number. */ + uint16_t version_16 = version_32 & 0xFFFF; + pfs_identity id; + id = container_id; + id <<= 16; + id += page_id; + id <<= 16; + id += object_id; + id <<= 16; + id += version_16; + return id; +} + +std::atomic global_container_id{1}; + PFS_buffer_default_allocator default_mutex_allocator(& builtin_memory_mutex); PFS_mutex_container global_mutex_container(& default_mutex_allocator); @@ -880,4 +900,3 @@ void PFS_user_allocator::free_array(PFS_user_array *array) PFS_user_allocator user_allocator; PFS_user_container global_user_container(& user_allocator); - diff --git a/storage/perfschema/pfs_buffer_container.h b/storage/perfschema/pfs_buffer_container.h index c1cd9e644ef..c4305795892 100644 --- a/storage/perfschema/pfs_buffer_container.h +++ b/storage/perfschema/pfs_buffer_container.h @@ -33,7 +33,26 @@ #include "pfs_prepared_stmt.h" #include "pfs_builtin_memory.h" -#define USE_SCALABLE +typedef std::uint16_t pfs_container_id; +typedef std::uint16_t pfs_page_id; +typedef std::uint16_t pfs_object_id; + +/** + * Build an artificial object identity, for OBJECT_INSTANCE_BEGIN columns. + * To be globally unique, identity consists of: + * - the container id, so objects A and B from different containers + * (instrument classes) will not collide. Note that partitioned containers + * get a container id per partition. + * - the page id within the container + * - the object index within the page + * - the version number from the pfs_lock dirty_state, to resolve ABA + * problems + */ +extern pfs_identity make_identity(pfs_container_id container_id, + pfs_page_id page_id, pfs_object_id object_id, + pfs_dirty_state *dirty_state); + +extern std::atomic global_container_id; class PFS_opaque_container_page; class PFS_opaque_container; @@ -77,7 +96,9 @@ class PFS_buffer_default_array public: typedef T value_type; - value_type *allocate(pfs_dirty_state *dirty_state) + value_type *allocate(pfs_dirty_state *dirty_state, + pfs_container_id container_id, pfs_page_id page_id, + pfs_identity *id) { uint index; uint monotonic; @@ -97,10 +118,11 @@ public: if (pfs->m_lock.free_to_dirty(dirty_state)) { + if (id != nullptr) + *id = make_identity(container_id, page_id, index, dirty_state); return pfs; } monotonic= m_monotonic.m_u32.fetch_add(1); - } m_full= true; @@ -400,6 +422,11 @@ template ::max(), + "pfs_object_id field is only 16 bits"); + static_assert(PFS_PAGE_COUNT <= std::numeric_limits::max(), + "pfs_page_id field is only 16 bits"); + friend class PFS_buffer_scalable_iterator; /** @@ -427,6 +454,7 @@ public: PFS_buffer_scalable_container(allocator_type *allocator) { + m_container_id = global_container_id++; m_allocator= allocator; m_initialized= false; m_lost= 0; @@ -533,7 +561,7 @@ public: return get_row_count() * get_row_size(); } - value_type *allocate(pfs_dirty_state *dirty_state) + value_type *allocate(pfs_dirty_state *dirty_state, pfs_identity *id) { if (m_full) { @@ -578,7 +606,7 @@ public: if (array != NULL) { - pfs= array->allocate(dirty_state); + pfs = array->allocate(dirty_state, m_container_id, index, id); if (pfs != NULL) { /* Keep a pointer to the parent page, for deallocate(). */ @@ -695,7 +723,7 @@ public: } assert(array != NULL); - pfs= array->allocate(dirty_state); + pfs= array->allocate(dirty_state, m_container_id, current_page_count, id); if (pfs != NULL) { /* Keep a pointer to the parent page, for deallocate(). */ @@ -1019,6 +1047,7 @@ private: array_type * m_pages[PFS_PAGE_COUNT]; allocator_type *m_allocator; pthread_mutex_t m_critical_section; + pfs_container_id m_container_id; }; template @@ -1178,11 +1207,12 @@ public: return sum; } - value_type *allocate(pfs_dirty_state *dirty_state, uint partition) + value_type *allocate(pfs_dirty_state *dirty_state, uint partition, + pfs_identity *id) { assert(partition < PFS_PARTITION_COUNT); - return m_partitions[partition]->allocate(dirty_state); + return m_partitions[partition]->allocate(dirty_state, id); } void deallocate(value_type *safe_pfs) @@ -1373,116 +1403,60 @@ private: uint m_sub_index; }; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_mutex_basic_container; typedef PFS_partitioned_buffer_scalable_container PFS_mutex_container; -#else -typedef PFS_buffer_container PFS_mutex_container; -#endif typedef PFS_mutex_container::iterator_type PFS_mutex_iterator; extern PFS_mutex_container global_mutex_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_rwlock_container; -#else -typedef PFS_buffer_container PFS_rwlock_container; -#endif typedef PFS_rwlock_container::iterator_type PFS_rwlock_iterator; extern PFS_rwlock_container global_rwlock_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_cond_container; -#else -typedef PFS_buffer_container PFS_cond_container; -#endif typedef PFS_cond_container::iterator_type PFS_cond_iterator; extern PFS_cond_container global_cond_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_file_container; -#else -typedef PFS_buffer_container PFS_file_container; -#endif typedef PFS_file_container::iterator_type PFS_file_iterator; extern PFS_file_container global_file_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_socket_container; -#else -typedef PFS_buffer_container PFS_socket_container; -#endif typedef PFS_socket_container::iterator_type PFS_socket_iterator; extern PFS_socket_container global_socket_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_mdl_container; -#else -typedef PFS_buffer_container PFS_mdl_container; -#endif typedef PFS_mdl_container::iterator_type PFS_mdl_iterator; extern PFS_mdl_container global_mdl_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_setup_actor_container; -#else -typedef PFS_buffer_container PFS_setup_actor_container; -#endif typedef PFS_setup_actor_container::iterator_type PFS_setup_actor_iterator; extern PFS_setup_actor_container global_setup_actor_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_setup_object_container; -#else -typedef PFS_buffer_container PFS_setup_object_container; -#endif typedef PFS_setup_object_container::iterator_type PFS_setup_object_iterator; extern PFS_setup_object_container global_setup_object_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_table_container; -#else -typedef PFS_buffer_container PFS_table_container; -#endif typedef PFS_table_container::iterator_type PFS_table_iterator; extern PFS_table_container global_table_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_table_share_container; -#else -typedef PFS_buffer_container PFS_table_share_container; -#endif typedef PFS_table_share_container::iterator_type PFS_table_share_iterator; extern PFS_table_share_container global_table_share_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_table_share_index_container; -#else -typedef PFS_buffer_container PFS_table_share_index_container; -#endif typedef PFS_table_share_index_container::iterator_type PFS_table_share_index_iterator; extern PFS_table_share_index_container global_table_share_index_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_table_share_lock_container; -#else -typedef PFS_buffer_container PFS_table_share_lock_container; -#endif typedef PFS_table_share_lock_container::iterator_type PFS_table_share_lock_iterator; extern PFS_table_share_lock_container global_table_share_lock_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_program_container; -#else -typedef PFS_buffer_container PFS_program_container; -#endif typedef PFS_program_container::iterator_type PFS_program_iterator; extern PFS_program_container global_program_container; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_prepared_stmt_container; -#else -typedef PFS_buffer_container PFS_prepared_stmt_container; -#endif typedef PFS_prepared_stmt_container::iterator_type PFS_prepared_stmt_iterator; extern PFS_prepared_stmt_container global_prepared_stmt_container; @@ -1503,17 +1477,9 @@ public: void free_array(PFS_account_array *array); }; -#ifdef USE_SCALABLE -typedef PFS_buffer_scalable_container PFS_account_container; -#else -typedef PFS_buffer_container PFS_account_container; -#endif typedef PFS_account_container::iterator_type PFS_account_iterator; extern PFS_account_container global_account_container; @@ -1534,17 +1500,11 @@ public: void free_array(PFS_host_array *array); }; -#ifdef USE_SCALABLE typedef PFS_buffer_scalable_container PFS_host_container; -#else -typedef PFS_buffer_container PFS_host_container; -#endif typedef PFS_host_container::iterator_type PFS_host_iterator; extern PFS_host_container global_host_container; @@ -1577,17 +1537,8 @@ public: void free_array(PFS_thread_array *array); }; -#ifdef USE_SCALABLE -typedef PFS_buffer_scalable_container PFS_thread_container; -#else -typedef PFS_buffer_container PFS_thread_container; -#endif typedef PFS_thread_container::iterator_type PFS_thread_iterator; extern PFS_thread_container global_thread_container; @@ -1608,17 +1559,8 @@ public: void free_array(PFS_user_array *array); }; -#ifdef USE_SCALABLE -typedef PFS_buffer_scalable_container PFS_user_container; -#else -typedef PFS_buffer_container PFS_user_container; -#endif typedef PFS_user_container::iterator_type PFS_user_iterator; extern PFS_user_container global_user_container; diff --git a/storage/perfschema/pfs_events_waits.h b/storage/perfschema/pfs_events_waits.h index 93dcb136834..0c950c84a33 100644 --- a/storage/perfschema/pfs_events_waits.h +++ b/storage/perfschema/pfs_events_waits.h @@ -29,6 +29,7 @@ Events waits data structures (declarations). */ +#include "pfs.h" #include "pfs_column_types.h" #include "pfs_lock.h" #include "pfs_events.h" @@ -88,8 +89,8 @@ struct PFS_events_waits : public PFS_events PFS_metadata_lock *m_weak_metadata_lock; /** For weak pointers, target object version. */ uint32 m_weak_version; - /** Address in memory of the object instance waited on. */ - const void *m_object_instance_addr; + /** Identity of the object instance waited on. */ + pfs_identity m_object_instance_addr; /** Operation performed. */ enum_operation_type m_operation; /** @@ -154,4 +155,3 @@ void reset_table_io_waits_by_table_handle(); void reset_table_lock_waits_by_table_handle(); #endif - diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc index bf8421909ba..408a45c4d84 100644 --- a/storage/perfschema/pfs_host.cc +++ b/storage/perfschema/pfs_host.cc @@ -169,7 +169,7 @@ search: lf_hash_search_unpin(pins); - pfs= global_host_container.allocate(& dirty_state); + pfs= global_host_container.allocate(& dirty_state, NULL); if (pfs != NULL) { pfs->m_key= key; diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index dad6125fa83..550b37b3efa 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -297,18 +297,18 @@ void cleanup_file_hash(void) /** Create instrumentation for a mutex instance. @param klass the mutex class - @param identity the mutex address @return a mutex instance, or NULL */ -PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity) +PFS_mutex* create_mutex(PFS_mutex_class *klass, const void * /* identity */) { PFS_mutex *pfs; pfs_dirty_state dirty_state; + pfs_identity id; - pfs= global_mutex_container.allocate(& dirty_state, klass->m_volatility); + pfs= global_mutex_container.allocate(& dirty_state, klass->m_volatility, &id); if (pfs != NULL) { - pfs->m_identity= identity; + pfs->m_identity= id; pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; @@ -343,18 +343,18 @@ void destroy_mutex(PFS_mutex *pfs) /** Create instrumentation for a rwlock instance. @param klass the rwlock class - @param identity the rwlock address @return a rwlock instance, or NULL */ -PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity) +PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void * /* identity */) { PFS_rwlock *pfs; pfs_dirty_state dirty_state; + pfs_identity id; - pfs= global_rwlock_container.allocate(& dirty_state); + pfs= global_rwlock_container.allocate(& dirty_state, &id); if (pfs != NULL) { - pfs->m_identity= identity; + pfs->m_identity= id; pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; @@ -391,18 +391,18 @@ void destroy_rwlock(PFS_rwlock *pfs) /** Create instrumentation for a condition instance. @param klass the condition class - @param identity the condition address @return a condition instance, or NULL */ -PFS_cond* create_cond(PFS_cond_class *klass, const void *identity) +PFS_cond* create_cond(PFS_cond_class *klass, const void * /* identity */) { PFS_cond *pfs; pfs_dirty_state dirty_state; + pfs_identity id; - pfs= global_cond_container.allocate(& dirty_state); + pfs= global_cond_container.allocate(& dirty_state, &id); if (pfs != NULL) { - pfs->m_identity= identity; + pfs->m_identity= id; pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; @@ -523,7 +523,7 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, PFS_thread *pfs; pfs_dirty_state dirty_state; - pfs= global_thread_container.allocate(& dirty_state); + pfs= global_thread_container.allocate(& dirty_state, NULL); if (pfs != NULL) { pfs->m_thread_internal_id= @@ -848,6 +848,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, uint retry_count= 0; const uint retry_max= 3; pfs_dirty_state dirty_state; + pfs_identity id; search: @@ -870,9 +871,10 @@ search: return NULL; } - pfs= global_file_container.allocate(& dirty_state); + pfs= global_file_container.allocate(& dirty_state, &id); if (pfs != NULL) { + pfs->m_identity = id; pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; @@ -881,7 +883,6 @@ search: pfs->m_filename_length= normalized_length; pfs->m_file_stat.m_open_count= 1; pfs->m_file_stat.m_io_stat.reset(); - pfs->m_identity= (const void *)pfs; pfs->m_temporary= false; int res; @@ -1110,19 +1111,19 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs) Create instrumentation for a table instance. @param share the table share @param opening_thread the opening thread - @param identity the table address @return a table instance, or NULL */ PFS_table* create_table(PFS_table_share *share, PFS_thread *opening_thread, - const void *identity) + const void * /* identity */) { PFS_table *pfs; pfs_dirty_state dirty_state; + pfs_identity id; - pfs= global_table_container.allocate(& dirty_state); + pfs= global_table_container.allocate(& dirty_state, &id); if (pfs != NULL) { - pfs->m_identity= identity; + pfs->m_identity= id; pfs->m_share= share; pfs->m_io_enabled= share->m_enabled && flag_global_instrumentation && global_table_io_class.m_enabled; @@ -1294,6 +1295,7 @@ PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd, { PFS_socket *pfs; pfs_dirty_state dirty_state; + pfs_identity id; uint fd_used= 0; uint addr_len_used= addr_len; @@ -1304,13 +1306,13 @@ PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd, if (addr_len_used > sizeof(sockaddr_storage)) addr_len_used= sizeof(sockaddr_storage); - pfs= global_socket_container.allocate(& dirty_state); + pfs= global_socket_container.allocate(& dirty_state, &id); if (pfs != NULL) { + pfs->m_identity= id; pfs->m_fd= fd_used; /* There is no socket object, so we use the instrumentation. */ - pfs->m_identity= pfs; pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; @@ -1378,7 +1380,7 @@ void destroy_socket(PFS_socket *pfs) global_socket_container.deallocate(pfs); } -PFS_metadata_lock* create_metadata_lock(void *identity, +PFS_metadata_lock* create_metadata_lock(void * /* identity */, const MDL_key *mdl_key, opaque_mdl_type mdl_type, opaque_mdl_duration mdl_duration, @@ -1388,11 +1390,12 @@ PFS_metadata_lock* create_metadata_lock(void *identity, { PFS_metadata_lock *pfs; pfs_dirty_state dirty_state; + pfs_identity id; - pfs= global_mdl_container.allocate(& dirty_state); + pfs= global_mdl_container.allocate(& dirty_state, &id); if (pfs != NULL) { - pfs->m_identity= identity; + pfs->m_identity= id; pfs->m_enabled= global_metadata_class.m_enabled && flag_global_instrumentation; pfs->m_timed= global_metadata_class.m_timed; pfs->m_mdl_key.mdl_key_init(mdl_key); diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h index 868f772267c..2fe5b05f7b8 100644 --- a/storage/perfschema/pfs_instr.h +++ b/storage/perfschema/pfs_instr.h @@ -91,8 +91,8 @@ struct PFS_instr /** Instrumented mutex implementation. @see PSI_mutex. */ struct PFS_ALIGNED PFS_mutex : public PFS_instr { - /** Mutex identity, typically a pthread_mutex_t. */ - const void *m_identity; + /** Mutex identity. */ + pfs_identity m_identity; /** Mutex class. */ PFS_mutex_class *m_class; /** Instrument statistics. */ @@ -109,8 +109,8 @@ struct PFS_ALIGNED PFS_mutex : public PFS_instr /** Instrumented rwlock implementation. @see PSI_rwlock. */ struct PFS_ALIGNED PFS_rwlock : public PFS_instr { - /** RWLock identity, typically a pthread_rwlock_t. */ - const void *m_identity; + /** RWLock identity. */ + pfs_identity m_identity; /** RWLock class. */ PFS_rwlock_class *m_class; /** Instrument statistics. */ @@ -134,8 +134,8 @@ struct PFS_ALIGNED PFS_rwlock : public PFS_instr /** Instrumented cond implementation. @see PSI_cond. */ struct PFS_ALIGNED PFS_cond : public PFS_instr { - /** Condition identity, typically a pthread_cond_t. */ - const void *m_identity; + /** Condition identity. */ + pfs_identity m_identity; /** Condition class. */ PFS_cond_class *m_class; /** Condition instance usage statistics. */ @@ -148,8 +148,8 @@ struct PFS_ALIGNED PFS_file : public PFS_instr uint32 get_version() { return m_lock.get_version(); } - /** File identity */ - const void *m_identity; + /** File identity. */ + pfs_identity m_identity; /** File name. */ char m_filename[FN_REFLEN]; /** File name length in bytes. */ @@ -241,8 +241,8 @@ public: ulonglong m_owner_event_id; /** Table share. */ PFS_table_share *m_share; - /** Table identity, typically a handler. */ - const void *m_identity; + /** Table identity. */ + pfs_identity m_identity; /** Table statistics. */ PFS_table_stat m_table_stat; /** Current internal lock. */ @@ -266,8 +266,8 @@ struct PFS_ALIGNED PFS_socket : public PFS_instr uint32 get_version() { return m_lock.get_version(); } - /** Socket identity, typically int */ - const void *m_identity; + /** Socket identity. */ + pfs_identity m_identity; /** Owning thread, if applicable */ PFS_thread *m_thread_owner; /** Socket file descriptor */ @@ -291,7 +291,7 @@ struct PFS_ALIGNED PFS_metadata_lock : public PFS_instr { return m_lock.get_version(); } /** Lock identity. */ - const void *m_identity; + pfs_identity m_identity; MDL_key m_mdl_key; opaque_mdl_type m_mdl_type; opaque_mdl_duration m_mdl_duration; @@ -814,4 +814,3 @@ extern LF_HASH pfs_filename_hash; /** @} */ #endif - diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index 86cc6365c31..ea2e7a747bc 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -716,7 +716,7 @@ create_table_share_lock_stat() pfs_dirty_state dirty_state; /* Create a new record in table stat array. */ - pfs= global_table_share_lock_container.allocate(& dirty_state); + pfs= global_table_share_lock_container.allocate(& dirty_state, NULL); if (pfs != NULL) { /* Reset the stats. */ @@ -769,13 +769,11 @@ create_table_share_index_stat(const TABLE_SHARE *server_share, uint server_index pfs_dirty_state dirty_state; /* Create a new record in index stat array. */ - pfs= global_table_share_index_container.allocate(& dirty_state); + pfs= global_table_share_index_container.allocate(& dirty_state, NULL); if (pfs != NULL) { if (server_index == MAX_INDEXES) - { pfs->m_key.m_name_length= 0; - } else { KEY *key_info= server_share->key_info + server_index; @@ -1797,7 +1795,7 @@ search: */ } - pfs= global_table_share_container.allocate(& dirty_state); + pfs= global_table_share_container.allocate(& dirty_state, NULL); if (pfs != NULL) { pfs->m_key= key; @@ -2061,4 +2059,3 @@ void update_program_share_derived_flags(PFS_thread *thread) } /** @} */ - diff --git a/storage/perfschema/pfs_prepared_stmt.cc b/storage/perfschema/pfs_prepared_stmt.cc index 50e4e27bb1e..6985720eef1 100644 --- a/storage/perfschema/pfs_prepared_stmt.cc +++ b/storage/perfschema/pfs_prepared_stmt.cc @@ -75,23 +75,23 @@ void reset_prepared_stmt_instances() } PFS_prepared_stmt* -create_prepared_stmt(void *identity, +create_prepared_stmt(void * /* identity */, PFS_thread *thread, PFS_program *pfs_program, PFS_events_statements *pfs_stmt, uint stmt_id, const char* stmt_name, uint stmt_name_length) { PFS_prepared_stmt *pfs= NULL; pfs_dirty_state dirty_state; + pfs_identity id; /* Create a new record in prepared stmt stat array. */ - pfs= global_prepared_stmt_container.allocate(& dirty_state); + pfs= global_prepared_stmt_container.allocate(& dirty_state, &id); if (pfs != NULL) { + pfs->m_identity= id; /* Reset the stats. */ pfs->reset_data(); /* Do the assignments. */ - pfs->m_identity= identity; - pfs->m_sqltext_length= 0; if (stmt_name != NULL) diff --git a/storage/perfschema/pfs_prepared_stmt.h b/storage/perfschema/pfs_prepared_stmt.h index 1a06122382c..395b6e2c015 100644 --- a/storage/perfschema/pfs_prepared_stmt.h +++ b/storage/perfschema/pfs_prepared_stmt.h @@ -38,7 +38,7 @@ struct PFS_ALIGNED PFS_prepared_stmt : public PFS_instr { /** Column OBJECT_INSTANCE_BEGIN */ - const void *m_identity; + pfs_identity m_identity; /** STATEMENT_ID */ ulonglong m_stmt_id; diff --git a/storage/perfschema/pfs_program.cc b/storage/perfschema/pfs_program.cc index 20b0aaa8489..b10f00b7d52 100644 --- a/storage/perfschema/pfs_program.cc +++ b/storage/perfschema/pfs_program.cc @@ -232,7 +232,7 @@ search: &is_enabled, &is_timed); /* Else create a new record in program stat array. */ - pfs= global_program_container.allocate(& dirty_state); + pfs= global_program_container.allocate(& dirty_state, NULL); if (pfs != NULL) { /* Do the assignments. */ diff --git a/storage/perfschema/pfs_setup_actor.cc b/storage/perfschema/pfs_setup_actor.cc index 638b2e5648d..07b2dbd21cd 100644 --- a/storage/perfschema/pfs_setup_actor.cc +++ b/storage/perfschema/pfs_setup_actor.cc @@ -154,7 +154,7 @@ int insert_setup_actor(const String *user, const String *host, const String *rol PFS_setup_actor *pfs; pfs_dirty_state dirty_state; - pfs= global_setup_actor_container.allocate(& dirty_state); + pfs= global_setup_actor_container.allocate(& dirty_state, NULL); if (pfs != NULL) { set_setup_actor_key(&pfs->m_key, diff --git a/storage/perfschema/pfs_setup_object.cc b/storage/perfschema/pfs_setup_object.cc index a961c51d0e9..989c49979e8 100644 --- a/storage/perfschema/pfs_setup_object.cc +++ b/storage/perfschema/pfs_setup_object.cc @@ -157,7 +157,7 @@ int insert_setup_object(enum_object_type object_type, const String *schema, PFS_setup_object *pfs; pfs_dirty_state dirty_state; - pfs= global_setup_object_container.allocate(& dirty_state); + pfs= global_setup_object_container.allocate(& dirty_state, NULL); if (pfs != NULL) { set_setup_object_key(&pfs->m_key, object_type, diff --git a/storage/perfschema/pfs_user.cc b/storage/perfschema/pfs_user.cc index d83ee52a77d..e3ec2992fa1 100644 --- a/storage/perfschema/pfs_user.cc +++ b/storage/perfschema/pfs_user.cc @@ -166,7 +166,7 @@ search: lf_hash_search_unpin(pins); - pfs= global_user_container.allocate(& dirty_state); + pfs= global_user_container.allocate(& dirty_state, NULL); if (pfs != NULL) { pfs->m_key= key; diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc index dbfe98e105d..b6d3a34379e 100644 --- a/storage/perfschema/table_events_waits.cc +++ b/storage/perfschema/table_events_waits.cc @@ -39,8 +39,6 @@ THR_LOCK table_events_waits_current::m_table_lock; -#define OBJECT_INSTANCE_BEGIN(X) (((intptr)X) - ((intptr) &pfs_truncatable_acl)) - PFS_engine_table_share_state table_events_waits_current::m_share_state = { false /* m_checked */ @@ -253,7 +251,7 @@ int table_events_waits_common::make_table_object_columns(PFS_events_waits *wait) m_row.m_index_name_length= 0; } - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; return 0; } @@ -268,7 +266,7 @@ int table_events_waits_common::make_file_object_columns(PFS_events_waits *wait) m_row.m_object_type= "FILE"; m_row.m_object_type_length= 4; m_row.m_object_schema_length= 0; - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; if (safe_file->get_version() == wait->m_weak_version) { @@ -300,7 +298,7 @@ int table_events_waits_common::make_socket_object_columns(PFS_events_waits *wait m_row.m_object_type= "SOCKET"; m_row.m_object_type_length= 6; m_row.m_object_schema_length= 0; - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; if (safe_socket->get_version() == wait->m_weak_version) { @@ -434,7 +432,7 @@ int table_events_waits_common::make_metadata_lock_object_columns(PFS_events_wait if (m_row.m_object_name_length > 0) memcpy(m_row.m_object_name, mdl->name(), m_row.m_object_name_length); - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; } else { @@ -500,17 +498,17 @@ void table_events_waits_common::make_row(PFS_events_waits *wait) break; case WAIT_CLASS_MUTEX: clear_object_columns(); - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; safe_class= sanitize_mutex_class((PFS_mutex_class*) wait->m_class); break; case WAIT_CLASS_RWLOCK: clear_object_columns(); - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; safe_class= sanitize_rwlock_class((PFS_rwlock_class*) wait->m_class); break; case WAIT_CLASS_COND: clear_object_columns(); - m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); + m_row.m_object_instance_addr= wait->m_object_instance_addr; safe_class= sanitize_cond_class((PFS_cond_class*) wait->m_class); break; case WAIT_CLASS_TABLE: @@ -1163,4 +1161,3 @@ table_events_waits_history_long::get_row_count(void) { return events_waits_history_long_size; } - diff --git a/storage/perfschema/table_events_waits.h b/storage/perfschema/table_events_waits.h index 85a9b146745..5ddf57582d1 100644 --- a/storage/perfschema/table_events_waits.h +++ b/storage/perfschema/table_events_waits.h @@ -79,7 +79,7 @@ struct row_events_waits /** Length in bytes of @c m_index_name. */ uint m_index_name_length; /** Column OBJECT_INSTANCE_BEGIN. */ - intptr m_object_instance_addr; + pfs_identity m_object_instance_addr; /** Column SOURCE. */ char m_source[COL_SOURCE_SIZE]; /** Length in bytes of @c m_source. */ diff --git a/storage/perfschema/table_events_waits_summary.cc b/storage/perfschema/table_events_waits_summary.cc index c848ebf4418..d0502932ec7 100644 --- a/storage/perfschema/table_events_waits_summary.cc +++ b/storage/perfschema/table_events_waits_summary.cc @@ -83,7 +83,7 @@ table_events_waits_summary_by_instance void table_events_waits_summary_by_instance ::make_instr_row(PFS_instr *pfs, PFS_instr_class *klass, - const void *object_instance_begin, + pfs_identity object_instance_begin, PFS_single_stat *pfs_stat) { pfs_optimistic_state lock; @@ -97,7 +97,7 @@ void table_events_waits_summary_by_instance m_row.m_name= klass->m_name; m_row.m_name_length= klass->m_name_length; - m_row.m_object_instance_addr= (intptr) object_instance_begin; + m_row.m_object_instance_addr= object_instance_begin; get_normalizer(klass); m_row.m_stat.set(m_normalizer, pfs_stat); @@ -161,11 +161,7 @@ void table_events_waits_summary_by_instance::make_file_row(PFS_file *pfs) PFS_single_stat sum; pfs->m_file_stat.m_io_stat.sum_waits(& sum); - /* - Files don't have a in memory structure associated to it, - so we use the address of the PFS_file buffer as object_instance_begin - */ - make_instr_row(pfs, safe_class, pfs, & sum); + make_instr_row(pfs, safe_class, pfs->m_identity, & sum); } /** @@ -186,11 +182,7 @@ void table_events_waits_summary_by_instance::make_socket_row(PFS_socket *pfs) PFS_byte_stat pfs_stat; pfs->m_socket_stat.m_io_stat.sum(&pfs_stat); - /* - Sockets don't have an associated in-memory structure, so use the address of - the PFS_socket buffer as object_instance_begin. - */ - make_instr_row(pfs, safe_class, pfs, &pfs_stat); + make_instr_row(pfs, safe_class, pfs->m_identity, &pfs_stat); } int table_events_waits_summary_by_instance @@ -240,4 +232,3 @@ int table_events_waits_summary_by_instance return 0; } - diff --git a/storage/perfschema/table_events_waits_summary.h b/storage/perfschema/table_events_waits_summary.h index 74f3a9ac959..0135b5e9aa9 100644 --- a/storage/perfschema/table_events_waits_summary.h +++ b/storage/perfschema/table_events_waits_summary.h @@ -48,7 +48,7 @@ struct row_events_waits_summary_by_instance /** Length in bytes of @c m_name. */ uint m_name_length; /** Column OBJECT_INSTANCE_BEGIN. */ - intptr m_object_instance_addr; + pfs_identity m_object_instance_addr; /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */ PFS_stat_row m_stat; }; @@ -65,7 +65,7 @@ public: protected: void make_instr_row(PFS_instr *pfs, PFS_instr_class *klass, - const void *object_instance_begin, + pfs_identity object_instance_begin, PFS_single_stat *pfs_stat); void make_mutex_row(PFS_mutex *pfs) override; void make_rwlock_row(PFS_rwlock *pfs) override; diff --git a/storage/perfschema/table_file_summary_by_instance.cc b/storage/perfschema/table_file_summary_by_instance.cc index 89e08d49161..a622430df88 100644 --- a/storage/perfschema/table_file_summary_by_instance.cc +++ b/storage/perfschema/table_file_summary_by_instance.cc @@ -203,7 +203,7 @@ int table_file_summary_by_instance::read_row_values(TABLE *table, m_row.m_event_name.set_field(f); break; case 2: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (ulonglong)m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 3:/* COUNT_STAR */ diff --git a/storage/perfschema/table_file_summary_by_instance.h b/storage/perfschema/table_file_summary_by_instance.h index 09f4383394d..34a91663b8e 100644 --- a/storage/perfschema/table_file_summary_by_instance.h +++ b/storage/perfschema/table_file_summary_by_instance.h @@ -50,8 +50,9 @@ struct row_file_summary_by_instance /** Column EVENT_NAME. */ PFS_event_name_row m_event_name; - /** Column OBJECT_INSTANCE_BEGIN */ - const void *m_identity; + /** Column OBJECT_INSTANCE_BEGIN. */ + pfs_identity m_identity; + /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER and NUMBER_OF_BYTES for READ, WRITE and MISC operation types. diff --git a/storage/perfschema/table_helper.h b/storage/perfschema/table_helper.h index 35039b47ccc..bfd15d8af0f 100644 --- a/storage/perfschema/table_helper.h +++ b/storage/perfschema/table_helper.h @@ -700,4 +700,3 @@ private: /** @} */ #endif - diff --git a/storage/perfschema/table_md_locks.cc b/storage/perfschema/table_md_locks.cc index e7b76c12764..54d91623012 100644 --- a/storage/perfschema/table_md_locks.cc +++ b/storage/perfschema/table_md_locks.cc @@ -177,7 +177,7 @@ int table_metadata_locks::read_row_values(TABLE *table, m_row.m_object.set_nullable_field(f->field_index, f); break; case 3: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (intptr) m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 4: /* LOCK_TYPE */ set_field_mdl_type(f, m_row.m_mdl_type, m_row.m_object.m_object_type == OBJECT_TYPE_BACKUP); @@ -211,4 +211,3 @@ int table_metadata_locks::read_row_values(TABLE *table, return 0; } - diff --git a/storage/perfschema/table_md_locks.h b/storage/perfschema/table_md_locks.h index 62f681435f6..47b8f6f78ae 100644 --- a/storage/perfschema/table_md_locks.h +++ b/storage/perfschema/table_md_locks.h @@ -43,7 +43,7 @@ struct PFS_metadata_lock; struct row_metadata_lock { /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; opaque_mdl_type m_mdl_type; opaque_mdl_duration m_mdl_duration; opaque_mdl_status m_mdl_status; diff --git a/storage/perfschema/table_prepared_stmt_instances.cc b/storage/perfschema/table_prepared_stmt_instances.cc index f064d8f03ae..0ad60048be5 100644 --- a/storage/perfschema/table_prepared_stmt_instances.cc +++ b/storage/perfschema/table_prepared_stmt_instances.cc @@ -235,7 +235,7 @@ int table_prepared_stmt_instances switch(f->field_index) { case 0: /* OBJECT_INSTANCE_BEGIN */ - set_field_ulonglong(f, (intptr)m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 1: /* STATEMENT_ID */ set_field_ulonglong(f, m_row.m_stmt_id); @@ -298,4 +298,3 @@ int table_prepared_stmt_instances return 0; } - diff --git a/storage/perfschema/table_prepared_stmt_instances.h b/storage/perfschema/table_prepared_stmt_instances.h index 838deec55a0..80ccdd620f6 100644 --- a/storage/perfschema/table_prepared_stmt_instances.h +++ b/storage/perfschema/table_prepared_stmt_instances.h @@ -43,7 +43,7 @@ struct row_prepared_stmt_instances { /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; /** Column STMT_ID. */ ulonglong m_stmt_id; diff --git a/storage/perfschema/table_socket_instances.cc b/storage/perfschema/table_socket_instances.cc index 2435d19df3c..8d2d8d92335 100644 --- a/storage/perfschema/table_socket_instances.cc +++ b/storage/perfschema/table_socket_instances.cc @@ -184,7 +184,7 @@ int table_socket_instances::read_row_values(TABLE *table, set_field_varchar_utf8(f, m_row.m_event_name, m_row.m_event_name_length); break; case 1: /* OBJECT_INSTANCE_BEGIN */ - set_field_ulonglong(f, (intptr)m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 2: /* THREAD_ID */ if (m_row.m_thread_id_set) diff --git a/storage/perfschema/table_socket_instances.h b/storage/perfschema/table_socket_instances.h index 61cb121afd4..e5e0f7ea0a1 100644 --- a/storage/perfschema/table_socket_instances.h +++ b/storage/perfschema/table_socket_instances.h @@ -44,7 +44,7 @@ struct row_socket_instances /** Length in bytes of @c m_event_name. */ uint m_event_name_length; /** Column OBJECT_INSTANCE_BEGIN */ - const void *m_identity; + pfs_identity m_identity; /** Column THREAD_ID */ ulonglong m_thread_id; /** True if thread_is is set */ diff --git a/storage/perfschema/table_socket_summary_by_instance.cc b/storage/perfschema/table_socket_summary_by_instance.cc index eb0568c05c2..3182e8f3deb 100644 --- a/storage/perfschema/table_socket_summary_by_instance.cc +++ b/storage/perfschema/table_socket_summary_by_instance.cc @@ -195,7 +195,7 @@ int table_socket_summary_by_instance::read_row_values(TABLE *table, m_row.m_event_name.set_field(f); break; case 1: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (intptr)m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 2:/* COUNT_STAR */ diff --git a/storage/perfschema/table_socket_summary_by_instance.h b/storage/perfschema/table_socket_summary_by_instance.h index 2f51d8b5e39..1ed679621fd 100644 --- a/storage/perfschema/table_socket_summary_by_instance.h +++ b/storage/perfschema/table_socket_summary_by_instance.h @@ -49,7 +49,7 @@ struct row_socket_summary_by_instance PFS_event_name_row m_event_name; /** Column OBJECT_INSTANCE_BEGIN */ - const void *m_identity; + pfs_identity m_identity; /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER and NUMBER_OF_BYTES for each operation. */ PFS_socket_io_stat_row m_io_stat; diff --git a/storage/perfschema/table_sync_instances.cc b/storage/perfschema/table_sync_instances.cc index 497f7fa1854..2cf8cc65db4 100644 --- a/storage/perfschema/table_sync_instances.cc +++ b/storage/perfschema/table_sync_instances.cc @@ -174,7 +174,7 @@ int table_mutex_instances::read_row_values(TABLE *table, set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length); break; case 1: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (intptr) m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 2: /* LOCKED_BY_THREAD_ID */ if (m_row.m_locked) @@ -334,7 +334,7 @@ int table_rwlock_instances::read_row_values(TABLE *table, set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length); break; case 1: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (intptr) m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 2: /* WRITE_LOCKED_BY_THREAD_ID */ if (m_row.m_write_locked) @@ -480,7 +480,7 @@ int table_cond_instances::read_row_values(TABLE *table, set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length); break; case 1: /* OBJECT_INSTANCE */ - set_field_ulonglong(f, (intptr) m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; default: assert(false); @@ -490,4 +490,3 @@ int table_cond_instances::read_row_values(TABLE *table, return 0; } - diff --git a/storage/perfschema/table_sync_instances.h b/storage/perfschema/table_sync_instances.h index 1a6cf81a173..2807b45d7c2 100644 --- a/storage/perfschema/table_sync_instances.h +++ b/storage/perfschema/table_sync_instances.h @@ -48,7 +48,7 @@ struct row_mutex_instances /** Length in bytes of @c m_name. */ uint m_name_length; /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; /** True if column LOCKED_BY_THREAD_ID is not null. */ bool m_locked; /** Column LOCKED_BY_THREAD_ID. */ @@ -104,7 +104,7 @@ struct row_rwlock_instances /** Length in bytes of @c m_name. */ uint m_name_length; /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; /** True if column WRITE_LOCKED_BY_THREAD_ID is not null. */ bool m_write_locked; /** Column WRITE_LOCKED_BY_THREAD_ID. */ @@ -162,7 +162,7 @@ struct row_cond_instances /** Length in bytes of @c m_name. */ uint m_name_length; /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; }; /** Table PERFORMANCE_SCHEMA.COND_INSTANCES. */ diff --git a/storage/perfschema/table_table_handles.cc b/storage/perfschema/table_table_handles.cc index 7ea2b0a3316..82b5f9dd6a2 100644 --- a/storage/perfschema/table_table_handles.cc +++ b/storage/perfschema/table_table_handles.cc @@ -196,7 +196,7 @@ int table_table_handles::read_row_values(TABLE *table, m_row.m_object.set_field(f->field_index, f); break; case 3: /* OBJECT_INSTANCE_BEGIN */ - set_field_ulonglong(f, (intptr) m_row.m_identity); + set_field_ulonglong(f, m_row.m_identity); break; case 4: /* OWNER_THREAD_ID */ set_field_ulonglong(f, m_row.m_owner_thread_id); @@ -218,4 +218,3 @@ int table_table_handles::read_row_values(TABLE *table, return 0; } - diff --git a/storage/perfschema/table_table_handles.h b/storage/perfschema/table_table_handles.h index d2330104e5d..883849d415d 100644 --- a/storage/perfschema/table_table_handles.h +++ b/storage/perfschema/table_table_handles.h @@ -48,7 +48,7 @@ struct row_table_handles /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */ PFS_object_row m_object; /** Column OBJECT_INSTANCE_BEGIN. */ - const void *m_identity; + pfs_identity m_identity; /** Column OWNER_THREAD_ID. */ ulonglong m_owner_thread_id; /** Column OWNER_EVENT_ID. */ diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index 3a33d1b8a4c..2d3fc776af8 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -211,11 +211,8 @@ IF(UNIX AND NOT WITHOUT_SERVER) ENDIF() IF((HAVE_SYSTEMD OR INSTALL_SYSTEMD_TMPUSERS) AND INSTALL_SYSTEMD_TMPFILESDIR) - IF(MYSQL_DATADIR STREQUAL INSTALL_RUNDATADIR) - SET(DISABLE_RUNDATADIR "#") - ENDIF() get_filename_component(MYSQL_UNIX_ADDRDIR ${MYSQL_UNIX_ADDR} DIRECTORY) - IF(MYSQL_UNIX_ADDRDIR STREQUAL MYSQL_DATADIR OR MYSQL_UNIX_ADDRDIR STREQUAL INSTALL_RUNDATADIR) + IF(MYSQL_UNIX_ADDRDIR STREQUAL MYSQL_DATADIR OR MYSQL_UNIX_ADDRDIR STREQUAL INSTALL_RUNDIR) SET(DISABLE_MYSQL_UNIX_ADDRDIR "#") ENDIF() diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index 84c7da3bfc6..a18716fc856 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -65,21 +65,9 @@ ProtectControlGroups=true # Prevent accessing /home, /root and /run/user ProtectHome=true -# Use an environment file to pass variable _WSREP_NEW_CLUSTER -EnvironmentFile=-@INSTALL_RUNDATADIR@/wsrep-new-cluster - -# Use an environment file to pass variable _WSREP_START_POSITION -EnvironmentFile=-@INSTALL_RUNDATADIR@/wsrep-start-position - -# Perform automatic wsrep recovery. When server is started without wsrep, -# galera_recovery simply returns an empty string. In any case, however, -# the script is not expected to return with a non-zero status. -# It is always safe to remove @INSTALL_RUNDATADIR@/wsrep-start-position -# environment file. -# Do not panic if galera_recovery script is not available. (MDEV-10538) -ExecStartPre=/bin/sh -c "[ ! -e @bindir@/galera_recovery ] && VAR= || \ - VAR=`@bindir@/galera_recovery`; [ $? -eq 0 ] \ - && echo _WSREP_START_POSITION=$VAR > @INSTALL_RUNDATADIR@/wsrep-start-position || exit 1" +# Use an environment file to pass variable _WSREP_NEW_CLUSTER. +# Must not be writable by mysql user. +EnvironmentFile=-@INSTALL_RUNDIR@/mariadb-wsrep-new-cluster # Needed to create system tables etc. # ExecStartPre=@scriptdir@/mariadb-install-db @@ -89,10 +77,17 @@ ExecStartPre=/bin/sh -c "[ ! -e @bindir@/galera_recovery ] && VAR= || \ # Use the [Service] section and Environment="MYSQLD_OPTS=...". # This isn't a replacement for my.cnf. # _WSREP_NEW_CLUSTER is for the exclusive use of the script galera_new_cluster -ExecStart=@sbindir@/mariadbd $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION +# +# Perform automatic wsrep recovery. When server is started without wsrep, +# galera_recovery simply returns an empty string. In any case, however, it is +# not expected to return a non-zero status. +ExecStart=/bin/sh -c "set -f; [ ! -e @bindir@/galera_recovery ] && VAR= || \ + VAR=`@bindir@/galera_recovery`; [ $? -eq 0 ] || exit 1; \ + exec @sbindir@/mariadbd $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $VAR" -# Unset _WSREP_START_POSITION/_WSREP_NEW_CLUSTER environment variable. -ExecStartPost=/bin/rm -f @INSTALL_RUNDATADIR@/wsrep-start-position @INSTALL_RUNDATADIR@/wsrep-new-cluster +# have to set the name explicitly now, otherwise it'll be the +# first name from ExecStart +SyslogIdentifier=mariadbd @SYSTEMD_EXECSTARTPOST@ diff --git a/support-files/rpm/server-prein.sh b/support-files/rpm/server-prein.sh index af04b343910..95dd464830a 100644 --- a/support-files/rpm/server-prein.sh +++ b/support-files/rpm/server-prein.sh @@ -68,6 +68,8 @@ fi # Create a MariaDB user and group. Do not report any problems if it already exists. groupadd -r %{mysqld_group} 2> /dev/null || true -useradd -M -r --home %{mysqldatadir} --shell /sbin/nologin --comment "MariaDB server" --gid %{mysqld_group} %{mysqld_user} 2> /dev/null || true +useradd -M -r --home /nonexistent --shell /sbin/nologin --comment "MariaDB server" --gid %{mysqld_group} %{mysqld_user} 2> /dev/null || true # The user may already exist, make sure it has the proper group nevertheless (BUG#12823) usermod --gid %{mysqld_group} %{mysqld_user} 2> /dev/null || true +# Make sure the home dir is correct too (must not be datadir) +usermod -d /nonexistent %{mysqld_user} 2> /dev/null || true diff --git a/support-files/tmpfiles.conf.in b/support-files/tmpfiles.conf.in index 6a2a28b59a3..e41585c08a8 100644 --- a/support-files/tmpfiles.conf.in +++ b/support-files/tmpfiles.conf.in @@ -1,9 +1,6 @@ # This is the directory where the unix socket # of MariaDB may be created. # -# Under Galera this is where an envfile of -# the Galera start position is stored. -# # Other temporary directories can be created here like: # * tmpdir # * innodb_tmpdir @@ -12,5 +9,4 @@ # etc. # It shouldn't be used for datadir which is why it # may be disabled. -@DISABLE_RUNDATADIR@d @INSTALL_RUNDATADIR@ 0755 @MYSQLD_USER@ @MYSQLD_USER@ - @DISABLE_MYSQL_UNIX_ADDRDIR@d @MYSQL_UNIX_ADDRDIR@ 0755 @MYSQLD_USER@ root -