Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-847: Fix OOB read in unpack_fields() on truncated metadata packet When processing server field packets in unpack_fields(), the 12-byte binary metadata envelope starting at row->data[i] (containing charsetnr, display length, field type, flags, decimals, and filler bytes) is read without validating that row->data[i] stays within row->length. A malformed or truncated field packet sent by a server/proxy can cause row->data[i] to point near or beyond row->length, resulting in an Out-of-Bounds (OOB) read when unpacking binary field metadata. Fix this by introducing a strict boundary check verifying that at least 12 bytes remain in the row buffer starting from row->data[i] before unpacking metadata fields. If the check fails, unpack_fields() fails gracefully, sets CR_MALFORMED_PACKET, and returns NULL. Also add unit tests (test_conc847_valid and test_conc847_invalid) covering both standard field packet parsing and truncated OOB packet handling. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
cleanup: only include my_compare.h into heap code as needed to avoid name conflict on `get_key_length` |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-36610 Subquery wrongly eliminated by table elimination When equality propagation (build_equal_items()) merges an equality that contains a subquery, such as "t1.a = (SELECT ...)", with an outer join's ON equality, it can inject a reference to that subquery into the ON expression. If the join columns have compatible types the subquery ends up as the constant of a multiple equality (which Item::walk() skips); if they differ (e.g. BIGINT vs INT) the field cannot be merged and the subquery is substituted in as a plain "tbl.col = (SELECT ...)" argument. In the latter case, if that outer join is removed by table elimination, mark_as_eliminated() walks the ON expression and flags the shared Item_subselect as eliminated. The subquery, however, still lives in another part of the query and has to be executed, tripping DBUG_ASSERT(!eliminated) in Item_subselect::exec() (and, in release builds, disabling the subquery cache and hiding it from EXPLAIN). The surviving reference can be: - a WHERE/HAVING/select-list/ORDER/GROUP expression (subquery written there and pushed down into the eliminated ON), or - the ON expression of an outer join that was not eliminated (subquery written in a surviving outer ON and pushed down into an eliminated inner one). Fix: after table elimination, walk the expressions that survive into execution (WHERE, HAVING, select list, ORDER/GROUP BY and the ON expressions of outer joins that were not eliminated) and clear the "eliminated" flag on any subquery still reachable from them. Because a subquery can also be the constant of a multiple equality, and Item::walk() does not visit an Item_equal's constant, Item_equal gets an unmark_as_eliminated_processor() override that descends into its constant explicitly. Assisted by Claude Opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '3.3-security' into 3.3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
generalize ROOT_FLAG_MPROTECT to work on Windows, rename accordingly * it's called ROOT_FLAG_VMEM * it does not imply any protection, ROOT_FLAG_MPROTECT was a misnomer * it means that the memory is allocated using my_virtual_mem_commit, not my_malloc, so not on heap * memory allocated this way can be protected with my_virtual_mem_protect() * thus root using ROOT_FLAG_VMEM can be protected with protect_root() Assisted-By: Claude:claude-5-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40411 SFORMAT ignores max_allowed_packet do our own allocator that implements std::allocator interface but uses our memory accounting (my_malloc) and limits max allocation (e.g. to max_allowed_packet). use it for fmt::vformat_to. later can be used for various std:: stuff too. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-846: Fix TLS verification check during auth-switch and certificate options logic Two issues resolved in TLS verification logic: 1. In run_plugin_auth(), the verification guard previously evaluated: (mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_TRUST) This allowed non-hashing plugins (e.g. mysql_clear_password) to execute when only hostname verification failed (MARIADB_TLS_VERIFY_HOST = 2), because (2 & 1) evaluated to 0. Updated the check to evaluate any non-zero tls_verify_status, ensuring all verification failures block cleartext auth switches. 2. Fixed TLS verification enabling when ssl_ca or crl options are specified even if MYSQL_OPT_SSL_VERIFY_SERVER_CERT (MARIADB_OPT_TLS_VERIFY_SERVER_CERT) was explicitly disabled. Certificate authority files/CRLs are now correctly honored and loaded according to caller intent. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40341 store read-only sysvars in a read-only root Store all READ_ONLY sysvar values in the read_only_root Even though READ_ONLY sysvars are protected, for string variables it usually means that the pointer cannot be changed. The value it points to - the string itself - still can be. Let's store all values of string READ_ONLY sysvars in the read_only_root. sysvars that point directly into argv are copied to read_only_root. sysvars that have their values calculated and allocated now must be explicitly marked with PREALLOCATED to let it know they have to be free()-d. Assisted-By: Claude:claude-4.8-opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40186 MEMORY tables incorrectly restart index scan on DELETE remember the last found key and restart the search (if needed) from it not from the original one. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Kristian Nielsen
knielsen@knielsen-hq.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39774: Assertion on slave with binlog_row_image=MINIMAL When finding the row to modify for a row event, and when not using rnd_pos_by_record() to locate the row, the code would use table->use_all_columns(), which makes the read_set and write_set point to the table->s->all_set in the table share. This caused problems when other code later modified bits in the read_set or write_set, which ends up wrongly modifying the table share. We can just use bitmap_set_all(table->read_set) to mark to read all columns and leave the possibility to later change the bits as needed. This code changes in this patch must be null-merged from 10.11 to 11.4, as there the problem is fixed differently. Signed-off-by: Kristian Nielsen <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fix leak in test_conc847_valid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39821 heap-use-after-free in heap_rnext with tree indexes heap_update() forgot to update key_changed |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Arcadiy Ivanov
arcadiy@ivanov.biz |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40378 heap: roll back key changes when a blob write fails in `heap_update()` `heap_update()` moves all changed key entries to the new key values **before** writing the new blob chains. When a blob chain write then failed (e.g. with `HA_ERR_RECORD_FILE_FULL`), the rollback restored the record bytes and blob chain pointers, but the `err:` label only undid key changes for `HA_ERR_FOUND_DUPP_KEY` -- historically the only possible failure once the key loop had run. The hash/btree entries were left keyed on the new values while pointing at a record holding the old values, corrupting the index: 1. index lookups by the old key value missed the row 2. `CHECK TABLE` reported the table corrupt 3. on debug builds the heap consistency check in `ha_heap::external_lock()` raised a second error into an already-set diagnostics area, firing a `Diagnostics_area` assertion on the next statement Fix: widen the `err:` recovery to run for `HA_ERR_RECORD_FILE_FULL`, `HA_ERR_OUT_OF_MEM` and `ENOMEM` as well, so a failure raised after the key loop also moves every changed key back to its old value. One recovery path now serves every failure that leaves keys moved to their new values, including any future error source in the key loop itself. The `err:` block assumed the failure happened **inside** the key loop, so that `keydef` addresses the partially processed keydef. A blob-chain write fails after that loop has run to completion, and therefore arrives with `keydef == keydef_end`. Reading `info->errkey` and `keydef->algorithm` from there addresses `share->keydef[share->keys]`; as `sizeof(HP_KEYDEF)` (888) far exceeds the key segments and blob descriptors that follow the keydef array, that read runs past the end of the `HP_SHARE` allocation, and the rollback sweep then dereferences a garbage `keydef->seg` in `hp_rec_key_cmp()`. So the recovery distinguishes the two failure sites: with `keydef == keydef_end` there is no partly updated key to repair and none to name in `info->errkey`, and the sweep starts at the last keydef instead. The same branch also covers a table with no keys at all (`share->keys == 0`), where the sweep has nothing to do. `info->errkey` is initialized to `-1` on entry to `err:`, so a failure that is not a key error can never expose a stale key number from an earlier operation. The original errno is captured before the recovery and restored after it, so that a rollback `write_key` failure (which `hp_rb_write_key()` reports as `HA_ERR_FOUND_DUPP_KEY` with a stale `errkey`) cannot mask it. The new test `heap.blob_update_key_rollback` exercises hash, BTREE, two changed indexes, an index on an unchanged column (which the rollback must leave untouched), a partial multi-row UPDATE, and a table with no indexes at all; each asserts the table stays consistent after the failure via `CHECK TABLE` and index lookups. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix OOB read in init_read_hdr() via dynamic column header validation In mariadb_dyncol.c, init_read_hdr() computed header pointer offsets and hdr->data_size without validating that the sum of fixed_hdr, header_size, and nmpool_size fit within str->length. Crafted dynamic column blobs with invalid metadata could push pointer offsets past the buffer bounds or cause unsigned integer underflow on hdr->data_size, leading to out-of-bounds reads in downstream functions. Add bounds check in init_read_hdr() to ensure header offsets do not exceed total buffer length, matching mariadb_dyncol_check(). Reported-by: AISLE Research |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-847: Fix OOB read in unpack_fields() on truncated metadata packet When processing server field packets in unpack_fields(), the 12-byte binary metadata envelope starting at row->data[i] (containing charsetnr, display length, field type, flags, decimals, and filler bytes) is read without validating that row->data[i] stays within row->length. A malformed or truncated field packet sent by a server/proxy can cause row->data[i] to point near or beyond row->length, resulting in an Out-of-Bounds (OOB) read when unpacking binary field metadata. Fix this by introducing a strict boundary check verifying that at least 12 bytes remain in the row buffer starting from row->data[i] before unpacking metadata fields. If the check fails, unpack_fields() fails gracefully, sets CR_MALFORMED_PACKET, and returns NULL. Also add unit tests (test_conc847_valid and test_conc847_invalid) covering both standard field packet parsing and truncated OOB packet handling. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Daniel Black
daniel@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40552 UBSAN: not a valid value for wkbByteOrder Gis_multi_point The byteorder field could contain an invalid value (> 1) on a GIS multi_point object where there byteorder was on any of the inner points. This can occur with any of the GIS "*FromWKB" functions that contained a multipoint object. This result in a invalid object being accepted and also potentially trigger undefined behaviour in the processing of the object. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-36610 Subquery wrongly eliminated by table elimination When equality propagation (build_equal_items()) merges an equality that contains a subquery, such as "t1.a = (SELECT ...)", with an outer join's ON equality, it can inject a reference to that subquery into the ON expression. If the join columns have compatible types the subquery ends up as the constant of a multiple equality (which Item::walk() skips); if they differ (e.g. BIGINT vs INT) the field cannot be merged and the subquery is substituted in as a plain "tbl.col = (SELECT ...)" argument. In the latter case, if that outer join is removed by table elimination, mark_as_eliminated() walks the ON expression and flags the shared Item_subselect as eliminated. The subquery, however, still lives in another part of the query and has to be executed, tripping DBUG_ASSERT(!eliminated) in Item_subselect::exec() (and, in release builds, disabling the subquery cache and hiding it from EXPLAIN). The surviving reference can be: - a WHERE/HAVING/select-list/ORDER/GROUP expression (subquery written there and pushed down into the eliminated ON), or - the ON expression of an outer join that was not eliminated (subquery written in a surviving outer ON and pushed down into an eliminated inner one). Fix: after table elimination, walk the expressions that survive into execution (WHERE, HAVING, select list, ORDER/GROUP BY and the ON expressions of outer joins that were not eliminated) and clear the "eliminated" flag on any subquery still reachable from them. Because a subquery can also be the constant of a multiple equality, and Item::walk() does not visit an Item_equal's constant, Item_equal gets an unmark_as_eliminated_processor() override that descends into its constant explicitly. Assisted by Claude Opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Revert "Remove length checks in mthd_stmt_fetch_to_bind, keep only the sentinel" This reverts commit 47a31a98750fd7c805ba67414c6d3df787ce8b2c. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '3.4-security' into 3.4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Daniel Black
daniel@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Remove no_valgrind_without_big.inc from *C* include dir The identical file is in mysql-test/include where it is used. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
cleanup: make my_virtual_mem_reserve() portable, unify buf0buf.cc make my_virtual_mem_reserve() work on Windows and on Linux (falling back to my_large_virtual_alloc() - that's what InnoDB did instead). This makes the usage pattern portable without #ifdef: - reserve a memory range - commit (allocate) memory from a reserved range - decommit memory, keeping it reserved - release reserved memory back to OS |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-23086 Error codes/messages reveal information about table structure if a user tries to access a table or a database they have no priivleges on, the error is alwaus "access denied", independently from whether the object exists or not. Do the same for columns. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40538 : Galera MDL-conflict logging does not work correctly Problem was that wsrep_log_state allocated buffer for String object, but did not set current length. In wsrep_get_state wsrep transaction state values was appended to this object but it current length was same as maximum length allocated leading to fact that nothing happened. Fixed by setting String object current length to 0 as it does not yet contain anything and fixed actual WSREP_DEBUG format. Removed debug only test case from galera_bf_kill because same test is on galera_bf_kill_debug test case. This allows following (1) galera_bf_kill test case can be run on both release and debug builds with same result file (2) galera_bf_kill_debug is run on debug only because it requires debug sync |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CONC-820: Clamp server-provided field lengths to maximum bounds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38056 Assertion 'bpage->state() >= buf_page_t::UNFIXED' in buf_page_get_zip() Three callers reconstruct old versions of a clustered index record, derive secondary index entries from them, and dereference the BLOB pointers of externally stored columns: row_vers_impl_x_locked_low() for the implicit lock check, row_undo_mod_sec_is_unsafe() for rollback, and row_check_index() for CHECK TABLE ... EXTENDED. purge_sys.view is what keeps those pages allocated, but purge_sys_t::view_guard froze it only for the duration of trx_undo_prev_version_build(), and the dereference happens after. On ROW_FORMAT=COMPRESSED this trips the assertion above; in a release build the freed page is read anyway, which is silent corruption. All three now hold purge_sys.latch across the dereference, and only where the version has externally stored columns, since row_build() dereferences nothing otherwise. Freezing that late means the view may have advanced since the walk decided a version was reachable, so each caller re-establishes that under the freeze, by testing the oldest writer whose undo log record it applied. That covers the newer ones: a newer version can only have been written once the older writer released the exclusive lock on the record. The first two can treat the test as an invariant, and end the walk if it fails. row_check_index() cannot: it decides reachability from purge_sys.end_view, which lags behind, and that lag is how it finds orphan secondary index records. It therefore stops where the test fails, as if the version chain had ended, which is how a version that can no longer be rebuilt is treated as well. Its two purge_sys.is_purgeable() tests now read the frozen view, which makes them atomic with the fetch they guard. trx_undo_prev_version(): remove the gate that was meant to stop CHECK TABLE ... EXTENDED from fetching BLOBs it may no longer own, and view_guard::is_extended() with it, which no guard mode could satisfy. That decision belongs to the caller, the only one that knows whether it will dereference anything. trx_purge(): a debug-only keyword that holds a batch open between its last purged record and purge_sys_t::batch_cleanup(), which is the window where a reader that goes by purge_sys.end_view can still reach history the batch has removed. innodb.old_blob_updel needs that window, and it is not otherwise addressable from a test, because it opens and closes within one batch. Tests: old_blob and old_blob_updel for the implicit lock check, old_blob_rollback for rollback, old_blob_check for CHECK TABLE ... EXTENDED. Each parks a walk at a dereference, makes the BLOB freeable, and asserts that the counter of purged update records, which is what would free it, stays at zero while parked and advances once the walk is over. old_blob_updel covers an undo log record that stores only the 20-byte reference; old_blob_rollback parks at a reference that the version merely inherited. All four fail with the original assertion when the freeze is removed, and skip above a 16k page size, which ROW_FORMAT=COMPRESSED requires. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39468 Mariabackup: redo log copier stalls and fails with misleading error message Problem: ======== During backup process, log copier thread stalls at lsn and fails with the misleading "Was only able to copy log from X to Y, not Z; try increasing innodb_log_file_size", even when the redo was intact and the log far from full. Problem is that copier advances recv_sys.lsn only on CRC-validated mtr, but it parses the redo at the server is concurrently writing to it. InnoDB rewrites the current partial write block repeatedly as mini-transaction fills it, so an mmap read (or) pread of a page being written can observe a torn/intermediate image of the tail block. If that tail block happens to parse as a longer mtr which is still valid, has a correct CRC then recv_sys.lsn, recv_sys.offset gets advanced wrongly and points to middle of the mini-transaction. In that case, later parse return GOT_EOF always and copier thread never reaches target and fails Solution: ========= Poll the server's durably-flushed LSN (status var Innodb_lsn_flushed) and limit the redo log copier based on it. backup_log_parse(): parses one mtr and if it exceeds the limit rolls back recv_sys.lsn/offset and reports GOT_EOF; the copier re-parses those bytes on a later pass once the fence has advanced past them. Used on both the mmap and buffered paths. log_copying_thread(): opens its own connection (it runs concurrently with the main thread, which owns mysql_connection) and refreshes the max_limit for parsing of redo log in each pass. In the final backup phase (BACKUP STAGE BLOCK_COMMIT) it gates on the exact target max(metadata_last_lsn, metadata_to_lsn). so the last partial block is copied in full up to the target. The stall diagnostic / retry spin is suppressed on a reached_parse_limit wait so a normal "caught up, wait" is not misreported as drift. get_log_flushed_lsn(): Added to get log_flushed_lsn from SHOW STATUS outout; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cleanup: main.view test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40341 store read-only sysvars in a read-only segment Protect all READ_ONLY sysvars from run-time changes. Put them into a separate section and use my_virtual_mem_protect() to make this section read-only before the server starts accepting connections. Verify that they're all protected in the sys_var constructor. One exception: opt_noacl (--skip-grant-tables) can be changed from 1 to 0 on FLUSH PRIVILEGES. Let's briefly drop the protection for this 1->0 change. It can be needed only once in a server lifetime and only if it was started with --skip-grant-tables On shutdown the protection is removed, making variables writable again because shutdown resets some of them during the cleanup Assisted-By: Claude:claude-4.8-opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40337 store user vars in a dedicated memroot user_var_entry objects and their names have a connection lifetime, they exist until the connection ends (or is reset), and then they're all deleted at once. This is exactly the use case for MEM_ROOT, let's store them there. Additionally, let's set MY_ROOT_USE_VMEM flag to keep this memroot off the general heap where user_var_entry values are stored and where heap buffer overflows can happen. The latter makes memory allocations for the MEM_ROOT about 10x more expensive, so let's always start with an empty memroot (= zero overhead if no user variables are used) and on THD cleanup let's retain one memroot block (= zero overhead if the next connection takes THD from the cache and uses user variables up to one block size). Assisted-By: Claude:claude-4.8-opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-36610 Subquery wrongly eliminated by table elimination When equality propagation (build_equal_items()) merges an equality that contains a subquery, such as "t1.a = (SELECT ...)", with an outer join's ON equality, it can inject a reference to that subquery into the ON expression. If the join columns have compatible types the subquery ends up as the constant of a multiple equality (which Item::walk() skips); if they differ (e.g. BIGINT vs INT) the field cannot be merged and the subquery is substituted in as a plain "tbl.col = (SELECT ...)" argument. In the latter case, if that outer join is removed by table elimination, mark_as_eliminated() walks the ON expression and flags the shared Item_subselect as eliminated. The subquery, however, still lives in another part of the query and has to be executed, tripping DBUG_ASSERT(!eliminated) in Item_subselect::exec() (and, in release builds, disabling the subquery cache and hiding it from EXPLAIN). The surviving reference can be: - a WHERE/HAVING/select-list/ORDER/GROUP expression (subquery written there and pushed down into the eliminated ON), or - the ON expression of an outer join that was not eliminated (subquery written in a surviving outer ON and pushed down into an eliminated inner one). Fix: after table elimination, walk the expressions that survive into execution (WHERE, HAVING, select list, ORDER/GROUP BY and the ON expressions of outer joins that were not eliminated) and clear the "eliminated" flag on any subquery still reachable from them. Because a subquery can also be the constant of a multiple equality, and Item::walk() does not visit an Item_equal's constant, Item_equal gets an unmark_as_eliminated_processor() override that descends into its constant explicitly. Assisted by Claude Opus |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '3.3' into 3.4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Kristian Nielsen
knielsen@knielsen-hq.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix earlier incorrect search/replace The errorneous replacements were from this commit: commit e680c21ce5c563493c60a0df1a8f867854920252 Author: Monty <[email protected]> Date: Sat Jan 24 17:13:52 2026 +0200 Fixed compilation failures in InnoDB with gcc 7.5.0 Signed-off-by: Kristian Nielsen <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Daniel Black
daniel@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39113 MSAN/ADDR addr2line stack resolver detrimental MSAN/ASAN test environment, the addr2line was so high in memory utilization that it was the pick of the OOM killer to resolve the OOM situation. Once this occurred there wasn't a saved core or gdb backtrace of the core to resolve the issue. To resolve this, make stack-trace default to 0 (off) for the addr2line base implementation under memory sanitizer and address sanitizer. MariaDB-backup also forces the enabling of stack-trace. Disabling this unconditionally reduces the risk of a user operational impact if a lengthy stack trace starting in a mariadb-backup critical locked period. The mysqld--help test now excludes the stack-trace as its result is environment dependant. The "Defaults to..." output for suppressed variables, currently only stack-trace, is excluded. Since thread-stack is an excluded varable, the ubsan/asan exclusions from commits dfa6fba9595a and dfa6fba9595a aren't required. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||