Home - Waterfall Grid T-Grid Console Builders Recent Builds Buildslaves Changesources - JSON API - About

Console View


Categories: connectors experimental galera main
Legend:   Passed Failed Warnings Failed Again Running Exception Offline No data

connectors experimental galera main
ARaveala
MDEV-39762: Slave Overflow on Malformed Query_compressed_log_event

A replica can crash when a compressed event from its master carries a
corrupted uncompressed length. A compressed Query event whose length
is near 4GB overwrites the IO thread's stack with the event's content.
A compressed rows event of the same shape makes the replica ask for an
allocation of 4GB. A debug build that gets that memory then fails an
assertion in binlog_buf_uncompress(). On a build where a ulong is 32
bits wide, both events overwrite the IO thread's stack.

The IO thread uncompresses a compressed event before writing the event
to the relay log, and offers the uncompress function 4096 bytes of its
own stack to hold the result. The function computes how large the event
will be once uncompressed, and that size decides where the uncompressed
event goes. An event that fits in the stack buffer is uncompressed
there. A larger event is uncompressed into an allocation the function
makes at that size. With either buffer, the function tells zlib that
the room available is the uncompressed length the event declared.

query_event_uncompress() never bounded the length read out of the
event. The function added the header length to that value, rounded the
sum up for alignment, and cast the result to uint32. The cast dropped
the high bits of a sum above 4GB, so a length near 4GB produced a size
of a few dozen bytes. That size fit the stack buffer, so content of any
size went onto the IO thread's stack. row_log_event_uncompress()
computes that sum in a ulong, which wraps where a ulong is 32 bits
wide. The Query_compressed_log_event constructor and
Rows_log_event::uncompress_buf() size their allocations from the same
unbounded length.

Reject an uncompressed length above MAX_MAX_ALLOWED_PACKET at every
point the length is read, before any size is computed from it. No
master writes a larger length, because max_allowed_packet is capped at
1GB. query_event_uncompress() also keeps that size in a size_t, so the
allocation is made from the whole computed value. Both functions return
the error code for the IO thread to report, so a length over the limit
stops the IO thread with ER_TOO_BIG_FOR_UNCOMPRESS rather than the
generic uncompress error. A compressed event with a corrupted
uncompressed length now stops the replica's IO thread with an error
instead of crashing the replica.

Alexandra Raveala wrote the original patch and its first regression
test, contributed through PR 5413. Brandon Nesterenko saw the work
through for the 10.6 release, replacing the test with one that makes
the master write the corrupt length and reworking how the IO thread
reports the error.

Co-authored-by: Brandon Nesterenko <[email protected]>
Reviewed-by: Kristian Nielsen <[email protected]>
PranavKTiwari
MDEV-40167: GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes
Problem:
GLOBAL TEMPORARY tables were not subject to the same option/index restrictions as session TEMPORARY tables. Several InnoDB and server-layer checks tested only tmp_table(), so GLOBAL TEMPORARY tables could bypass validation for VECTOR/FULLTEXT indexes, DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED.

Cause:
global_tmp_table() was added as a separate predicate from tmp_table(), but not all temp-table checks were updated to test both, so GLOBAL TEMPORARY tables fell through to "permanent table" logic in several places.

Fix:
Added global_tmp_table() alongside tmp_table() at each affected check:

Reject VECTOR and FULLTEXT indexes on GLOBAL TEMPORARY tables.
Reject/warn on DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED for GLOBAL TEMPORARY tables, with accurate wording in the DATA DIRECTORY warning.
Fixed zip_allowed and related ut_ad assertions to exclude GLOBAL TEMPORARY tables.
Fixed m_use_file_per_table in set_tablespace_type() to exclude GLOBAL TEMPORARY tables (also fixes m_use_data_dir).
GLOBAL TEMPORARY tables now validate the same as session TEMPORARY tables across these options.
Marko Mäkelä
Merge InnoDB_backup::logs to InnoDB_backup::queue
Brandon Nesterenko
MDEV-40648: Replication Undefined Behavior on Malformed Rotate Log Event

A slave stops with a relay log read failure when its master sends an
event whose header declares a length other than the number of bytes the
event arrived in. The file and position the slave reports for that
failure are not where the problem is. A master that logs no checksum
does not stop the slave at all. Such a master can make the slave run one
statement twice, leaving the slave's data holding a row the master's
binary log never carried. A "malicious" master can already send whatever
events it likes, so what this defeats is comparing a slave's applied
stream against the master's binary log.

The slave IO thread reads each event from the master as one network
packet, and writes that packet into the relay log unchanged, using the
packet's own length. Every later reader of that relay log frames the
events by a different length: the one each event's header declares at
EVENT_LEN_OFFSET. A master writing an event sets the two to the same
value. Log_event::read_log_event(), which parses the events that
queue_event() does not construct itself, checks only that the packet
reaches EVENT_LEN_OFFSET, and never compares the declared length with
the length of the packet.

queue_event() never compared the two lengths either. An event declaring
fewer bytes than the packet held reached the relay log with the extra
bytes behind the event. The SQL thread framed its next read from inside
the previous event. Where the master had placed a complete event in
those extra bytes, and no checksum covered the packet, the SQL thread
applied that second event.

This patch adds validation to ensure the lengths are equal. An event
whose lengths disagree will stop the IO thread with
ER_SLAVE_FATAL_ERROR, and the relay log will never receive the event.

Reviewed-by: TODO
Signed-off-by: Brandon Nesterenko <[email protected]>
Sergei Golubchik
ft_json ft parser
Daniel Black
MDEV-40572 SIGSEGV in JSON_OVERLAPS()

on a truncated nested JSON object with different character sets/collations.

The value->s.c_str and js->s.c_str became invalid once the
function returned which caused the crash.
sjaakola
MDEV-38243 Write binlog row events for changes done by cascading FK operations

This commit implements a feature which changes the handling of cascading foreign
key operations to write the changes of cascading operations into binlog.
The applying of such transaction, in the slave node, will apply just the binlog
events, and does not execute the actual foreign key cascade operation.
This will simplify the slave side replication applying and make it more predictable
in terms of potential interference with other parallel applying happning
in the node.

This feature can be turned ON/OFF by new variable:
rpl_use_binlog_events_for_fk_cascade, with default value OFF

The actual implementation is largely by windsurf.

The commit has also mtr tests for testing rpl_use_binlog_events_for_fk_cascade
feature:  rpl.rpl_fk_cascade_binlog_row, rpl.rpl_fk_set_null_binlog_row and
rpl.fk_cascade_binlog_row_rollback
sjaakola
MDEV-38243 Write binlog row events for changes done by cascading FK operations

Refactoring according to Serg's review. In this version, SE/server API now
narrows the SE role to just report the changes done by foreign key cascading,
and server side does most of the work after that.

Added a design document MDEV-38243-design.md
forkfun
MDEV-39146 Fix use-after-free/UAF races on THD::security_ctx

SQL SECURITY DEFINER switches (events, stored routines, views,
virtual columns) repoint thd->security_ctx without synchronizing
with PROCESSLIST/KILL, which read it from other threads under
LOCK_thd_data. For events specifically, the DEFINER context is
stack-allocated in Event_job_data::execute(), so a concurrent
PROCESSLIST read can dereference it after the frame is gone.

- Add THD::set_security_context() as the single locked chokepoint
  for repointing security_ctx; convert all writers to use it.
- Lock COM_CHANGE_USER's failed-auth free()+restore of ->user.
- Lock kill_threads_callback()'s identity match test.
- thd_visible_in_processlist()/processlist_callback()/list_callback():
  trylock (never block, avoids stalling the whole server), falling
  back to priv_user/priv_host (fixed arrays, never freed) on
  contention instead of the freed/switched heap pointers.
Brandon Nesterenko
MDEV-40643: Corrupt Heartbeat Log Event can Crash Slave

A slave can crash when its master sends an event shorter than the
event's own header. A truncated heartbeat makes debug builds fail an
assertion in Binary_string::realloc_raw(). On 64-bit release builds it
stops the slave IO thread with an error message that omits the log
file name. If the master also declares an oversized common header in
its format description event, the slave allocates and fills nearly 4GB
instead. On 32-bit release builds it writes that error message past
the end of a stack buffer. An event under four bytes crashes every
build, because the slave checksums roughly 16 EiB and reads far past
the end of the packet.

Neither queue_event() nor the Heartbeat_log_event constructor bounded
the length the master sent. queue_event() handed that length to
event_checksum_test(), which subtracted the checksum length from it,
and the result wrapped on an event under four bytes. The constructor
computed the log file name length as event_len minus the header
lengths, and on a truncated heartbeat that subtraction wrapped to a
value near 4GB. queue_event() rejected the heartbeat as invalid, so
its error path appended the log file name to the error message using
the wrapped length.

Add the missing bound in both places. queue_event() now rejects an event
shorter than the common header before anything reads that header, and
the slave IO thread stops with an error. The Heartbeat_log_event
constructor now compares event_len against the combined header lengths
before the subtraction. A heartbeat that clears the first check but
still stops inside its headers keeps ident_len at 0 and log_ident at
NULL, so the error path appends nothing. That constructor check also
precedes the read of the extended log position, which previously ran on
a short event before any validation. A short event from the master now
stops the slave IO thread with an error instead of crashing the server.

Reviewed-by: Kristian Nielsen <[email protected]>
Signed-off-by: Brandon Nesterenko <[email protected]>
forkfun
MDEV-40584 ST_CROSSES always returns 0 for different-dimension geometries

MDEV-36058 added a dimension-equality check ("Both geometries must
have the same number of dimensions") for SP_OVERLAPS_FUNC, but a
stray fall-through from SP_CROSSES_FUNC into that same case made
CROSSES share it too. CROSSES is defined precisely for geometries
of different dimensions, so any such pair now hit
"if (g1_dim != g2_dim) DBUG_RETURN(0)" and always returned 0.

Give SP_CROSSES_FUNC its own case again, calling
handle_sp_crosses_func_case() directly without the dimension check.
SP_OVERLAPS_FUNC keeps the check.
Brandon Nesterenko
MDEV-40646 (Regression): Undersized Table_map Metadata can Crash Slave
bsrikanth-mariadb
MDEV-40553: unprintable gis ranges in trace and context

When ranges were specified in a query for GIS types, the recorded trace
and context couldn't print the range information. Instead, it only
showed unprintable_geometry_value.

This PR extends the geometric field type Field_geom to print appropriate
key value, along with the comparison operator when printed in the range.
Key value is decoded from binary if applicable, and is recorded in WKT
format. For spatial indexes, the operators like MBRWITHIN, MBRCONTAINS, etc...
are stored appropriately, and for normal indexes, operators like
<, <=, >, >=, etc... are recorded appropriately.

Implementation Details: -
1. overwrite print_key_value() for Field_geom to print the decoded
  binary value in WKT format. If binary value can't be decoded
  appropriately to WKT format, then the binary value itself is recorded.
2. Add an argument imagetype to Field::print_key_part_value(), to determine
  if an index key part value is to be printed in WKT or binary format.
  For Geometric type, imagetype is set to itMBR. When printing ranges,
  the MBR operators are printed as well, as implemented in
  print_mbr_range_operator().
sjaakola
MDEV-38243 Write binlog row events for changes done by cascading FK operations

Fixes according to Kristian Nielsen's review:
* Removed obsolete checks for slave thread
* Supporting slave with old MariaDB version.
  Events logged in cascade operation are additionally flagged with
  the long-standing NO_FOREIGN_KEY_CHECKS_F, so a replica that does
  not understand FK_CASCADE_EVENTS_F still disables foreign key checks
  and  does not re-execute the cascade

Also, thee are now binlog event flags to mark both original and derived
events. This will make it possible for the slave to choose whether to use
the derived events in applying or to execute the cascade operation

There is a new test rpl.rpl_fk_cascade_binlog_row_old_slave, for checking
compatibility with replication slave of old mariadb version
Brandon Nesterenko
MDEV-40648 (Regression): Replication Undefined Behavior on Malformed Rotate Log Event

test
Yuchen Pei
[demo] Do not call lock_rec_convert_impl_to_expl if a table S-lock is held

In lock_clust_rec_read_check_and_lock there's a test on
lock_table_has(trx, index->table, LOCK_X) which if fails would result
in a call to lock_rec_convert_impl_to_expl<true>, which 1. has a
comment "If an implicit x-lock exists on a record, convert it to an
explicit one." that does not apply if a table S-lock is held and 2.
does a few things such as looking up the trx_id of the record and find
the trx in a global hash trx_sys. In this patch we do the same check
for a table S-lock. This could potentially improve the performance of
LOCK IN SHARE MODE (TODO: check)
PranavKTiwari
MDEV-25515 User Account Host Names using CIDR notation

  Accept CIDR notation (RFC 4632) as an alternative spelling of the
  ip/netmask host form, matching MySQL 8.0.23 (WL#14074):

    CREATE USER u@'192.168.0.0/24';  -- same as '192.168.0.0/255.255.255.0'

  update_hostname() tries the dotted-quad mask first and falls back to the
  new calc_cidr(), so both spellings yield the same acl_host_and_ip and are
  interchangeable wherever a host is used - user, db, table, routine and
  proxy privileges, and the plugin API.  IPv4 only.  The host string is
  stored and reported verbatim; neither spelling is normalised.

  Add is_valid_masked_host(), rejecting at DDL time what was previously
  accepted and left silently unusable:

    - a prefix outside 1..32, or a mask of 0.0.0.0
    - a non-contiguous mask, e.g. 10.0.0.0/255.0.255.0
    - an address with host bits set, e.g. 10.1.2.3/24
    - anything containing '/' that is not a dotted quad, including IPv6
      prefixes such as 2001:db8::/32

  The check runs in replace_user_table(), covering CREATE USER and every
  GRANT variant that can auto-create an account, and in mysql_rename_user()
  for the rename target.  It applies only to rows about to be created:

    - existing rows are not validated, so an account created by an older
      version stays revocable, renamable and droppable
    - acl_load() is unchanged, so a malformed row in the privilege tables
      cannot prevent the server from starting
    - RENAME USER validates the target only, so such an account can be
      repaired by renaming it onto a valid host

  New error ER_INVALID_HOST_NETMASK.

  acl_user_compare() now compares ip_mask before the host string, treating
  an unmasked host as /32, so the most specific subnet wins:

    u@'10.0.0.0/24' is preferred over u@'10.0.0.0/8'

  This corrects precedence for existing netmask accounts as well, and
  applies to acl_users only; acl_dbs, acl_hosts, acl_proxy_users and the
  table/routine grant hashes are left unchanged.
PranavKTiwari
MDEV-25515 User Account Host Names using CIDR notation

  Accept CIDR notation (RFC 4632) as an alternative spelling of the
  ip/netmask host form, matching MySQL 8.0.23 (WL#14074):

    CREATE USER u@'192.168.0.0/24';  -- same as '192.168.0.0/255.255.255.0'

  update_hostname() tries the dotted-quad mask first and falls back to the
  new calc_cidr(), so both spellings yield the same acl_host_and_ip and are
  interchangeable wherever a host is used - user, db, table, routine and
  proxy privileges, and the plugin API.  IPv4 only.  The host string is
  stored and reported verbatim; neither spelling is normalised.

  Add is_valid_masked_host(), rejecting at DDL time what was previously
  accepted and left silently unusable:

    - a prefix outside 1..32, or a mask of 0.0.0.0
    - a non-contiguous mask, e.g. 10.0.0.0/255.0.255.0
    - an address with host bits set, e.g. 10.1.2.3/24
    - anything containing '/' that is not a dotted quad, including IPv6
      prefixes such as 2001:db8::/32

  The check runs in replace_user_table(), covering CREATE USER and every
  GRANT variant that can auto-create an account, and in mysql_rename_user()
  for the rename target.  It applies only to rows about to be created:

    - existing rows are not validated, so an account created by an older
      version stays revocable, renamable and droppable
    - acl_load() is unchanged, so a malformed row in the privilege tables
      cannot prevent the server from starting
    - RENAME USER validates the target only, so such an account can be
      repaired by renaming it onto a valid host

  New error ER_INVALID_HOST_NETMASK.

  acl_user_compare() now compares ip_mask before the host string, treating
  an unmasked host as /32, so the most specific subnet wins:

    u@'10.0.0.0/24' is preferred over u@'10.0.0.0/8'

  This corrects precedence for existing netmask accounts as well, and
  applies to acl_users only; acl_dbs, acl_hosts, acl_proxy_users and the
  table/routine grant hashes are left unchanged.
Brandon Nesterenko
MDEV-40644 (Regression): Slave SQL Thread Overflow on Malformed Table_map_log_event
Mohammad Tafzeel Shams
MDEV-37467: InnoDB Instant ALTER TABLE is not crash safe

Instant ALTER TABLE metadata record includes externally stored
BLOB metadata. The existing BLOB storage path in
btr_store_big_rec_extern_fields() writes the clustered index record
first, with zero BLOB pointers, and only fills in the BLOB pointers
afterwards. If the server is killed after the mini-transaction that
wrote the (incomplete) metadata record was durably committed, but
before the BLOB pointers were written, the table could become
inaccessible on recovery.

Make metadata BLOB storage crash-safe by writing the BLOB pages and
computing their pointers before the metadata record itself is
inserted or updated, so that the record is always written with
complete BLOB pointers. If the server is killed before the metadata
record is written, the already-written BLOB pages are merely
orphaned, which is safe.

- btr_store_big_rec_metadata():
  New function to store the off-page columns of a metadata record
  ahead of time. Each BLOB page is allocated and linked in its own
  mini-transaction, and the resulting BLOB pointers are written
  directly into the (heap-resident) index entry. On failure, it frees
  any pages it already allocated and resets the pointers to zero.

- btr_free_big_rec_metadata():
  New helper to free the BLOB pages written by
  btr_store_big_rec_metadata() and reset the entry's BLOB pointers
  to zero, used both on failure inside that function and by its
  callers when the metadata record ends up not being written.

- row_ins_clust_index_entry_low():
  For a metadata entry that needs external storage, convert it to a
  big record and call btr_store_big_rec_metadata() (with
  log_free_check() allowed, since no latches are held yet) before
  inserting the record. On failure, free the metadata BLOBs and
  convert the entry back.

- btr_cur_pessimistic_update():
  When updating a metadata record that requires external storage,
  call btr_store_big_rec_metadata() (without log_free_check(),
  since index and page latches are held) before modifying the record,
  and free the temporary big_rec vector via btr_free_big_rec_metadata()
  or dtuple_big_rec_free() on the various failure/success paths.

- btr_cur_optimistic_insert():
  Remove the special-cased jump to convert_big_rec for metadata
  entries, since their BLOBs are now always stored ahead of time by
  the caller; assert that a metadata entry never needs external
  storage at this point.

- innobase_instant_try():
  Since btr_cur_pessimistic_update() now stores metadata BLOBs
  before updating the record, big_rec is always NULL here; assert
  this instead of calling btr_store_big_rec_extern_fields().

- Added test in innodb.instant_alter and innodb.instant_alter_crash
  to test normal working of INSTANT ALTER, crash safety and full table.
Alexander Barkov
MDEV-40722 DROP PACKAGE leaves PACKAGE BODY grant in mysql.procs_priv

DROP PACKAGE now removes both PACKAGE BODY and PACKAGE privileges
for the given package.
Yuchen Pei
MDEV-40632 Use my_fprintf in trx_print_low

To fix for windows %p in `fprintf(f, "TRANSACTION (%p)", trx);` is not
prefixed with 0x
Brandon Nesterenko
MDEV-40644: Slave SQL Thread Overflow on Malformed Table_map_log_event

A slave can crash when its master sends a Table_map event whose table
name is longer than an identifier can be. The SQL thread applying the
event copies the name into a fixed buffer and overruns it, and the SQL
thread crashes.

A Table_map event carries its database and table names each behind a
one-byte length. The constructor that parses the event sizes a buffer
for each name from its declared length, and do_apply_event() copies
both names out of the event into NAME_LEN+1 byte buffers with strmov().
strmov() copies up to the terminating null. A real identifier is at
most NAME_LEN bytes, so the name fits the buffer and carries that null.

The constructor never bounded the two lengths. Each length is read as a
byte, so each can reach 255. The constructor copied each name with
strncpy() over the declared length, which writes no terminating null
when the source holds none. do_apply_event() then copied the name into
its NAME_LEN+1 byte buffer with strmov(), which ran past the buffer
until it reached a null elsewhere in the heap. pack_info() read the
same names with %s for SHOW RELAYLOG EVENTS, past the buffer in the
same way.

Bound the lengths in the constructor. It now rejects a Table_map event
whose declared database name, or whose declared table name, exceeds
NAME_LEN, before it sizes the name buffers, so is_valid() returns
false. It also terminates each name it copies, so a source that holds
no null does not leave the name unterminated. A master naming a table
with an oversized name now stops the slave's SQL thread with
ER_SLAVE_RELAY_LOG_READ_FAILURE instead of crashing it.

Reviewed-by: TODO
Signed-off-by: Brandon Nesterenko <[email protected]>
PranavKTiwari
MDEV-25515 User Account Host Names using CIDR notation

  Accept CIDR notation (RFC 4632) as an alternative spelling of the
  ip/netmask host form, matching MySQL 8.0.23 (WL#14074):

    CREATE USER u@'192.168.0.0/24';  -- same as '192.168.0.0/255.255.255.0'

  update_hostname() tries the dotted-quad mask first and falls back to the
  new calc_cidr(), so both spellings yield the same acl_host_and_ip and are
  interchangeable wherever a host is used - user, db, table, routine and
  proxy privileges, and the plugin API.  IPv4 only.  The host string is
  stored and reported verbatim; neither spelling is normalised.

  Add is_valid_masked_host(), rejecting at DDL time what was previously
  accepted and left silently unusable:

    - a prefix outside 1..32, or a mask of 0.0.0.0
    - a non-contiguous mask, e.g. 10.0.0.0/255.0.255.0
    - an address with host bits set, e.g. 10.1.2.3/24
    - anything containing '/' that is not a dotted quad, including IPv6
      prefixes such as 2001:db8::/32

  The check runs in replace_user_table(), covering CREATE USER and every
  GRANT variant that can auto-create an account, and in mysql_rename_user()
  for the rename target.  It applies only to rows about to be created:

    - existing rows are not validated, so an account created by an older
      version stays revocable, renamable and droppable
    - acl_load() is unchanged, so a malformed row in the privilege tables
      cannot prevent the server from starting
    - RENAME USER validates the target only, so such an account can be
      repaired by renaming it onto a valid host

  New error ER_INVALID_HOST_NETMASK.

  acl_user_compare() now compares ip_mask before the host string, treating
  an unmasked host as /32, so the most specific subnet wins:

    u@'10.0.0.0/24' is preferred over u@'10.0.0.0/8'

  This corrects precedence for existing netmask accounts as well, and
  applies to acl_users only; acl_dbs, acl_hosts, acl_proxy_users and the
  table/routine grant hashes are left unchanged.
Brandon Nesterenko
MDEV-40648: Replication Undefined Behavior on Malformed Rotate Log Event

A slave stops with a relay log read failure when its master sends an
event whose header declares a length other than the number of bytes the
event arrived in. The file and position the slave reports for that
failure are not where the problem is. A master that logs no checksum
does not stop the slave at all. Such a master can make the slave run one
statement twice, leaving the slave's data holding a row the master's
binary log never carried. A "malicious" master can already send whatever
events it likes, so what this defeats is comparing a slave's applied
stream against the master's binary log.

The slave IO thread reads each event from the master as one network
packet, and writes that packet into the relay log unchanged, using the
packet's own length. Every later reader of that relay log frames the
events by a different length: the one each event's header declares at
EVENT_LEN_OFFSET. A master writing an event sets the two to the same
value. Log_event::read_log_event(), which parses the events that
queue_event() does not construct itself, checks only that the packet
reaches EVENT_LEN_OFFSET, and never compares the declared length with
the length of the packet.

queue_event() never compared the two lengths either. An event declaring
fewer bytes than the packet held reached the relay log with the extra
bytes behind the event. The SQL thread framed its next read from inside
the previous event. Where the master had placed a complete event in
those extra bytes, and no checksum covered the packet, the SQL thread
applied that second event.

This patch adds validation to ensure the lengths are equal. An event
whose lengths disagree will stop the IO thread with
ER_SLAVE_FATAL_ERROR, and the relay log will never receive the event.

Reviewed-by: Kristian Nielsen <[email protected]>
Signed-off-by: Brandon Nesterenko <[email protected]>
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

(Comment and code edited by Sergei Petrunia <[email protected]> and
Thirunarayanan Balathandayuthapani <[email protected]>)
PranavKTiwari
MDEV-test Remove tests failing on MSAN memory limits
Marko Mäkelä
Catch std::bad_alloc
Brandon Nesterenko
MDEV-40492: Oversized Fake Rotate Event can Crash Slave

A slave can crash when the master's binlog_checksum setting differs
from the checksum the slave's relay log carries. On the first Rotate
event of such a connection, the slave IO thread copies the event onto
a stack buffer sized for the longest binary log file name a master can
send. A master that names a longer file makes the copy run off the end
of that buffer, and what it writes past the end is the file name
itself. A name that overruns the buffer by a few hundred bytes reaches
only the other buffers of the same stack frame, which the slave does
not read on this path, so it keeps running. A name that overruns the
whole frame takes the return address with it, and the slave crashes.
Builds with AddressSanitizer stop at the copy and report a
stack-buffer-overflow.

The fake Rotate event that opens a connection is rewritten when the
master's checksum policy and the relay log's disagree. One case adds a
checksum to the event, and the other strips one. Both copy the event
into rot_buf using the length the master sent, and neither compared
that length against the size of rot_buf. The Rotate_log_event
constructed just above bounds its own copy of the file name at
FN_REFLEN-1, which leaves the length the master sent untouched.
rot_buf was itself one checksum shorter than the event the first case
produces from the longest file name.

Bound the event before either case copies it. queue_event() now
compares the event's length against the longest Rotate a master can
send: the two headers, a file name of at most FN_REFLEN bytes, and the
checksum the master's own policy puts on the event. rot_buf now
reserves that checksum length as well. A Rotate event naming a longer
file stops the slave IO thread with an error reporting the length the
master sent, instead of running off the end of the buffer.

Reviewed-by: Kristian Nielsen <[email protected]>
Signed-off-by: Brandon Nesterenko <[email protected]>
PranavKTiwari
MDEV-25515 User Account Host Names using CIDR notation

  Accept CIDR notation (RFC 4632) as an alternative spelling of the
  ip/netmask host form, matching MySQL 8.0.23 (WL#14074):

    CREATE USER u@'192.168.0.0/24';  -- same as '192.168.0.0/255.255.255.0'

  update_hostname() tries the dotted-quad mask first and falls back to the
  new calc_cidr(), so both spellings yield the same acl_host_and_ip and are
  interchangeable wherever a host is used - user, db, table, routine and
  proxy privileges, and the plugin API.  IPv4 only.  The host string is
  stored and reported verbatim; neither spelling is normalised.

  Add is_valid_masked_host(), rejecting at DDL time what was previously
  accepted and left silently unusable:

    - a prefix outside 1..32, or a mask of 0.0.0.0
    - a non-contiguous mask, e.g. 10.0.0.0/255.0.255.0
    - an address with host bits set, e.g. 10.1.2.3/24
    - anything containing '/' that is not a dotted quad, including IPv6
      prefixes such as 2001:db8::/32

  The check runs in replace_user_table(), covering CREATE USER and every
  GRANT variant that can auto-create an account, and in mysql_rename_user()
  for the rename target.  It applies only to rows about to be created:

    - existing rows are not validated, so an account created by an older
      version stays revocable, renamable and droppable
    - acl_load() is unchanged, so a malformed row in the privilege tables
      cannot prevent the server from starting
    - RENAME USER validates the target only, so such an account can be
      repaired by renaming it onto a valid host

  New error ER_INVALID_HOST_NETMASK.

  acl_user_compare() now compares ip_mask before the host string, treating
  an unmasked host as /32, so the most specific subnet wins:

    u@'10.0.0.0/24' is preferred over u@'10.0.0.0/8'

  This corrects precedence for existing netmask accounts as well, and
  applies to acl_users only; acl_dbs, acl_hosts, acl_proxy_users and the
  table/routine grant hashes are left unchanged.
Oleksandr Byelkin
Merge fix.
Brandon Nesterenko
MDEV-40646: Undersized Table_map Metadata can Crash Slave

A slave can crash or leak heap content when its master sends a Table_map
event that declares columns whose types need more field metadata than
the event carries. Building its description of the table, the slave
reads past the end of the field metadata the event holds. The bytes
beyond the buffer are decoded as column metadata.

A Table_map event carries a column count, one type byte per column,
and a block of field metadata. A column's type fixes how many metadata
bytes it consumes: two for the string, enum, set, bit, varchar, and
decimal types, one for the blob, float, and high precision temporal
types, none for the rest. The master writes exactly that many bytes
per column, so the metadata block a well formed event carries is the
sum over its columns. The slave sizes the metadata block from the
event and, while building its table_def, walks the columns in order
and reads each type's metadata bytes from that block.

The slave checked only that the metadata block was no larger than two
bytes per column. It never checked the block against the column types
themselves. table_def() then walked every declared column and indexed
the metadata block for each, so a column whose type needed metadata
the block did not hold read past the end of it. A column count large
enough carried that read far past the allocation.

The Table_map reader now sums the metadata the declared column types
consume and rejects the event when the block is smaller than that
sum, so is_valid() reports the event as invalid and the SQL thread
stops with a relay log read failure before any column is decoded. A
block larger than the sum is still accepted, because every consumer
reads only the bytes the types call for. A column type this slave
does not recognize counts as zero in the sum, so Table_map events
from a newer master using such a type still parse. A Table_map whose
metadata cannot cover its column types now stops the slave with an
error instead of reading past the buffer.

Note that the regression test does not crash a regular debug build;
an ASAN build is required to show the invalid memory access.  The 24
column table map it injects overruns the metadata allocation by a
bounded amount that lands in mapped heap, which a debug build reads
without faulting and then stops the SQL thread with
ER_SLAVE_CONVERSION_FAILED on the column type mismatch.

Reviewed-by: TODO
Signed-off-by: Brandon Nesterenko <[email protected]>
Alexander Barkov
MDEV-40722 DROP PACKAGE leaves PACKAGE BODY grant in mysql.procs_priv

10.6 version

DROP PACKAGE now removes both PACKAGE BODY and PACKAGE privileges
for the given package.
Alexander Barkov
MDEV-40722 DROP PACKAGE leaves PACKAGE BODY grant in mysql.procs_priv

DROP PACKAGE now removes both PACKAGE BODY and PACKAGE privileges
for the given package.
Brandon Nesterenko
MDEV-40644: Slave SQL Thread Overflow on Malformed Table_map_log_event

A slave can crash when its master sends a Table_map event whose table
name is longer than an identifier can be. The SQL thread applying the
event copies the name into a fixed buffer and overruns it, and the SQL
thread crashes.

A Table_map event carries its database and table names each behind a
one-byte length. The constructor that parses the event sizes a buffer
for each name from its declared length, and do_apply_event() copies
both names out of the event into NAME_LEN+1 byte buffers with strmov().
strmov() copies up to the terminating null. A real identifier is at
most NAME_LEN bytes, so the name fits the buffer and carries that null.

The constructor never bounded the two lengths. Each length is read as a
byte, so each can reach 255. The constructor copied each name with
strncpy() over the declared length, which writes no terminating null
when the source holds none. do_apply_event() then copied the name into
its NAME_LEN+1 byte buffer with strmov(), which ran past the buffer
until it reached a null elsewhere in the heap. pack_info() read the
same names with %s for SHOW RELAYLOG EVENTS, past the buffer in the
same way.

Bound the lengths in the constructor. It now rejects a Table_map event
whose declared database name, or whose declared table name, exceeds
NAME_LEN, before it sizes the name buffers, so is_valid() returns
false. It also terminates each name it copies, so a source that holds
no null does not leave the name unterminated. A master naming a table
with an oversized name now stops the slave's SQL thread with
ER_SLAVE_RELAY_LOG_READ_FAILURE instead of crashing it.

Reviewed-by: TODO
Signed-off-by: Brandon Nesterenko <[email protected]>
Thirunarayanan Balathandayuthapani
- Find the script even in non-linux environment

(cherry picked from commit 1370d5ab28c3475b1b77267d75935c33466f28ed)
Brandon Nesterenko
MDEV-40644 (Regression): Slave SQL Thread Overflow on Malformed Table_map_log_event
bsrikanth-mariadb
MDEV-40553: unprintable gis ranges in trace and context

When ranges were specified in a query for GIS types, the recorded trace
and context couldn't print the range information. Instead, it only
showed unprintable_geometry_value.

This PR extends the geometric field type Field_geom to print appropriate
key value, along with the comparison operator when printed in the range.
Key value is decoded from binary if applicable, and is recorded in WKT
format. For spatial indexes, the operators like MBRWITHIN, MBRCONTAINS, etc...
are stored appropriately, and for normal indexes, operators like
<, <=, >, >=, etc... are recorded appropriately.

Implementation Details: -
1. overwrite print_key_value() for Field_geom to print the decoded
  binary value in WKT format. If binary value can't be decoded
  appropriately to WKT format, then the binary value itself is recorded.
2. Add an argument imagetype to Field::print_key_part_value(), to determine
  if an index key part value is to be printed in WKT or binary format.
  For Geometric type, imagetype is set to itMBR. When printing ranges,
  the MBR operators are printed as well, as implemented in
  print_mbr_range_operator().
Daniel Black
MDEV-40165 JSON_EQUAL/JSON_NORMALIZE/JSON_CONTAINS error handling

Adds test cases that validate the incorrect null handling
in the 2894e90b6545d3c7fa13ff00fb50c9e8631003e7 commit
and other JSON_EQUALS,CONTAINS/OVERLAPS behaviour.