From 328ee0c01f4a47bb9b2443f314539e56ee1d3f12 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 18 May 2026 12:25:48 -0400 Subject: [PATCH 1/7] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e557ee31898..b8f92727248 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=4 -MYSQL_VERSION_PATCH=11 +MYSQL_VERSION_PATCH=12 SERVER_MATURITY=stable From e41fc224355224fe67d3f5d3acae530ba31a4b32 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 21 May 2026 13:33:54 +0200 Subject: [PATCH 2/7] CI - Fix Github Actions warning, bump actions/checkout version --- .github/workflows/windows-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-arm64.yml b/.github/workflows/windows-arm64.yml index a061849cc25..1fb8784b68e 100644 --- a/.github/workflows/windows-arm64.yml +++ b/.github/workflows/windows-arm64.yml @@ -24,7 +24,7 @@ jobs: # unless we configure autocrlf. git config --global core.autocrlf input - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install prerequisites run: | From e287c48d73272e1618156520c9c18b3768464a1b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 26 May 2026 09:10:47 +0200 Subject: [PATCH 3/7] improve MTR bootstrap performance on slow disk use --debug-no-sync to workaround slow disk flush. On Github actions Windows ARM64, this alone cuts the test time from ca 55 min to ca 45 min. --- mysql-test/mariadb-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 042bbf89132..3e0d5b2a380 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -3127,6 +3127,7 @@ sub mysql_install_db { mtr_add_arg($args, "--loose-innodb-log-file-size=10M"); mtr_add_arg($args, "--loose-innodb-fast-shutdown=0"); mtr_add_arg($args, "--disable-sync-frm"); + mtr_add_arg($args, "--debug-no-sync"); mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/"); mtr_add_arg($args, "--core-file"); mtr_add_arg($args, "--console"); From 323644c5912a49d798719472594826d0e540f006 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 22 May 2026 10:12:08 +0200 Subject: [PATCH 4/7] MDEV-39719 Fix memory allocation errors on Windows ARM64 CI Do not overload the machine. Huge reservation seem to stress Windows on ARM64 memory management, so that random OOM can appear when multiple processes are constantly allocating/deallocating huge chunks of memory. Thus, reduce number of parallel threads to 2, and do not run replication tests. --- .github/workflows/windows-arm64.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-arm64.yml b/.github/workflows/windows-arm64.yml index 1fb8784b68e..b5d54d3575c 100644 --- a/.github/workflows/windows-arm64.yml +++ b/.github/workflows/windows-arm64.yml @@ -46,12 +46,11 @@ jobs: - name: Test MTR run: | $env:PATH = "C:\Strawberry\perl\bin;$env:PATH;C:\Program Files (x86)\Windows Kits\10\Debuggers\arm64" - #Calculate parallel as 4 * number of processors - $parallel = 4 * [int]$env:NUMBER_OF_PROCESSORS + $parallel = 2 # create case-sensitive directory to run tests in $tmp = (Get-Item $env:TEMP).FullName $tmp = $tmp -replace '\\','/' $cidir = "$tmp/ci" mkdir $cidir fsutil file setCaseSensitiveInfo $cidir enable - perl bld\mysql-test\mysql-test-run.pl --force --parallel=$parallel --suite=main,innodb --vardir=$cidir/var --mysqld=--lower-case-table-names=0 --mysqld=--loose-innodb-flush-log-at-trx-commit=2 --mysqld=--debug-no-sync + perl bld\mysql-test\mysql-test-run.pl --force --parallel=$parallel --suite=main,innodb --vardir=$cidir/var --skip-rpl --mysqld=--lower-case-table-names=0 --mysqld=--loose-innodb-flush-log-at-trx-commit=2 --mysqld=--debug-no-sync --skip-test=innodb-virtual-columns \ No newline at end of file From 49a745395a2f9cbe50a43e0d6373ae3386b26889 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Wed, 27 May 2026 14:28:45 -0400 Subject: [PATCH 5/7] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b8f92727248..286d033b024 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=4 -MYSQL_VERSION_PATCH=12 +MYSQL_VERSION_PATCH=13 SERVER_MATURITY=stable From 478d6f5561e09a7502aad74e62b1afc2c72d23d6 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 23 May 2026 15:03:44 +1000 Subject: [PATCH 6/7] MDEV-37864 json_array_intersect result has incorrect length MDEV-37864 added a length setting to the function Item_func_json_array_intersect::prepare_json_and_create_hash however some paths of Item_func_json_array_intersect::fix_length_and_dec never reach this function. Leave the length calculation the same but place in the ::fix_length_and_dec function. Collation is based on the arg[0], but potentially after they are swapped. Corrects cursor protocol for the test case added in MDEV-36808. --- sql/item_jsonfunc.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 417464ce64d..4a6c5cc7168 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -5533,10 +5533,7 @@ bool Item_func_json_array_intersect::prepare_json_and_create_hash(json_engine_t report_json_error(js, je1, 0); } - max_length= 2*(args[0]->max_length < args[1]->max_length ? - args[0]->max_length : args[1]->max_length); - - return false; + return false; } bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd) @@ -5565,6 +5562,10 @@ bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd) } end: + collation.set(args[0]->collation); + fix_char_length_ulonglong((ulonglong) + 2* MY_MIN(args[0]->max_char_length(), + args[1]->max_char_length())); set_maybe_null(); return FALSE; } From d2ebea4febdbc102da09a3b51bea4ef2819a3843 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Thu, 28 May 2026 18:35:30 +0700 Subject: [PATCH 7/7] MDEV-38561: ASAN heap-use-after-free in Query_arena::free_items/sp_lex_cursor::~sp_lex_cursor On re-parsing of a failed cursor statement inside the stored routine, the free_list of sp_lex_cursor could point to items placed on a dedicated memory root that is created during re-parsing of the failed statement. In result, when sp_head object is destroyed the mem_root created for re-parsing the cursor's statement is de-allocated but the free_list pointer of sp_lex_cursor still point to objects previously allocated on this memory root. To fix the issue, delay deallocation of mem_roots created for re-parsing of SP instructions till the moment the sp_head be destroyed. --- mysql-test/main/sp_validation.result | 41 +++++++++++++++++++++++++- mysql-test/main/sp_validation.test | 43 +++++++++++++++++++++++++++- sql/sp_head.cc | 40 ++++++++++++++++++++++++++ sql/sp_head.h | 11 +++++++ sql/sp_instr.h | 12 ++++++-- 5 files changed, 143 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/sp_validation.result b/mysql-test/main/sp_validation.result index 0808fd7cd78..324ac71cb1a 100644 --- a/mysql-test/main/sp_validation.result +++ b/mysql-test/main/sp_validation.result @@ -2085,4 +2085,43 @@ DROP PROCEDURE p2; DROP PROCEDURE p3; DROP PROCEDURE p4; DROP TABLE t1; -SET sql_mode = default; +# +# MDEV-38561: ASAN heap-use-after-free in Query_arena::free_items/sp_lex_cursor::~sp_lex_cursor +# +SET @save_sql_mode=@@sql_mode; +SET sql_mode='oracle'; +CREATE OR REPLACE PACKAGE pkg1 AS +PROCEDURE p1 (); +PROCEDURE p2 (); +END pkg1; +$ +CREATE OR REPLACE PACKAGE BODY pkg1 AS +PROCEDURE p1() IS +CURSOR c1 IS SELECT a FROM t1; +va c1%ROWTYPE; +BEGIN +SELECT 1; +END p1; +PROCEDURE p2() is +BEGIN +FOR i IN 1..2 +LOOP +SELECT i; +CREATE OR REPLACE temporary TABLE t1 (a INT); +CALL pkg1.p1; +END loop; +END p2; +END pkg1 +$ +CALL pkg1.p2(); +i +1 +1 +1 +i +2 +1 +1 +DROP PACKAGE BODY pkg1; +DROP PACKAGE pkg1; +SET sql_mode=@save_sql_mode; diff --git a/mysql-test/main/sp_validation.test b/mysql-test/main/sp_validation.test index bf1f147deec..839024148dc 100644 --- a/mysql-test/main/sp_validation.test +++ b/mysql-test/main/sp_validation.test @@ -2886,5 +2886,46 @@ DROP PROCEDURE p3; DROP PROCEDURE p4; DROP TABLE t1; -SET sql_mode = default; +--echo # +--echo # MDEV-38561: ASAN heap-use-after-free in Query_arena::free_items/sp_lex_cursor::~sp_lex_cursor +--echo # +SET @save_sql_mode=@@sql_mode; +SET sql_mode='oracle'; + +--delimiter $ + +CREATE OR REPLACE PACKAGE pkg1 AS +PROCEDURE p1 (); +PROCEDURE p2 (); +END pkg1; +$ + +CREATE OR REPLACE PACKAGE BODY pkg1 AS +PROCEDURE p1() IS + CURSOR c1 IS SELECT a FROM t1; + va c1%ROWTYPE; +BEGIN + SELECT 1; +END p1; + +PROCEDURE p2() is +BEGIN + FOR i IN 1..2 + LOOP + SELECT i; + CREATE OR REPLACE temporary TABLE t1 (a INT); + CALL pkg1.p1; + END loop; +END p2; +END pkg1 +$ + +--delimiter ; +CALL pkg1.p2(); + +DROP PACKAGE BODY pkg1; +DROP PACKAGE pkg1; + +SET sql_mode=@save_sql_mode; + --enable_ps2_protocol diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5f4fb6f997e..2a60c381b44 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -904,6 +904,8 @@ sp_head::~sp_head() delete m_pcont; free_items(); + deallocate_sp_instrs_mem_roots(); + /* If we have non-empty LEX stack then we just came out of parser with error. Now we should delete all auxilary LEXes and restore original @@ -921,6 +923,44 @@ sp_head::~sp_head() } +/** + Iterate along a list of mem_roots created for reparsing of failed + SP instructions. There are as many mem_roots in this list as a number of + failed sp instructions. +*/ + +void sp_head::deallocate_sp_instrs_mem_roots() +{ + List_iterator_fast it(m_mem_roots_to_release); + MEM_ROOT *sp_instr_mem_root; + + while ((sp_instr_mem_root= it++)) + { + free_root(sp_instr_mem_root, MYF(0)); + } + m_mem_roots_to_release.empty(); +} + + +/** + Register the memory root for later deallocation + + @param mem_root the pointer to an instance of MEM_ROOT + + @return false on success, true on error +*/ + +bool sp_head::register_instr_mem_root_for_deallocation(MEM_ROOT *mem_root) +{ + DBUG_ASSERT(mem_root != nullptr); + + if (unlikely(mem_root == nullptr)) + return false; + + return m_mem_roots_to_release.push_back(mem_root); +} + + void sp_package::LexList::cleanup() { List_iterator it(*this); diff --git a/sql/sp_head.h b/sql/sp_head.h index 070b0a01ba3..3e845dc6def 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -333,6 +333,12 @@ private: */ const char *m_cpp_body_begin; + /** + List of pointers to MEM_ROOT objects created when re-parsing failing + SP instructions. + */ + List m_mem_roots_to_release; + public: /* Security context for stored routine which should be run under @@ -345,6 +351,11 @@ protected: enum_sp_aggregate_type agg_type); virtual ~sp_head(); public: + + void deallocate_sp_instrs_mem_roots(); + + bool register_instr_mem_root_for_deallocation(MEM_ROOT *mem_root); + static void destroy(sp_head *sp); static sp_head *create(sp_package *parent, const Sp_handler *handler, enum_sp_aggregate_type agg_type, diff --git a/sql/sp_instr.h b/sql/sp_instr.h index 908e602f005..dfd3d6d06af 100644 --- a/sql/sp_instr.h +++ b/sql/sp_instr.h @@ -400,7 +400,8 @@ public: sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner) : sp_instr(ip, ctx), m_lex_keeper(lex, is_lex_owner), - m_mem_root_for_reparsing(nullptr) + m_mem_root_for_reparsing(nullptr), + m_sp{lex->sphead} {} ~sp_lex_instr() override @@ -418,7 +419,13 @@ public: */ free_items(); m_lex_keeper.~sp_lex_keeper(); - free_root(m_mem_root_for_reparsing, MYF(0)); + + /* + Ignore the OOM error explicitly since we are inside destructor + */ + (void)m_sp->register_instr_mem_root_for_deallocation( + m_mem_root_for_reparsing); + m_mem_root_for_reparsing= nullptr; } } @@ -507,6 +514,7 @@ private: */ List cleanup_before_parsing(enum_sp_type sp_type); + sp_head *m_sp; /** Set up field object for every NEW/OLD item of the trigger and