Skip to content

Commit b4a5ad8

Browse files
committed
Merge mariadb-10.5.8 into 10.5
2 parents fff469d + 7da6353 commit b4a5ad8

File tree

7 files changed

+163
-36
lines changed

7 files changed

+163
-36
lines changed

mysql-test/main/range.result

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ SELECT * FROM t1 WHERE
12971297
25 <= a AND b = 23 OR
12981298
23 <= a;
12991299
id select_type table type possible_keys key key_len ref rows Extra
1300-
1 SIMPLE t1 range a a 5 NULL 2 Using where; Using index
1300+
1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index
13011301
SELECT * FROM t1 WHERE
13021302
23 <= a AND a <= 25 OR
13031303
25 <= a AND b = 23 OR
@@ -3121,6 +3121,39 @@ a b
31213121
set eq_range_index_dive_limit=default;
31223122
drop table t1;
31233123
#
3124+
# MDEV-24117: Memory management problem in statistics state...
3125+
# (just the testcase)
3126+
#
3127+
create table t0(a int);
3128+
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
3129+
create table t1(a int);
3130+
insert into t1
3131+
select A.a + B.a* 10 + C.a * 100 + D.a * 1000
3132+
from t0 A, t0 B, t0 C, t0 D
3133+
where D.a<4;
3134+
create table t2 (
3135+
a int,
3136+
b int,
3137+
key(a)
3138+
);
3139+
insert into t2 values (1,1),(2,2),(3,3);
3140+
set @query=(select group_concat(a) from t1);
3141+
set @tmp_24117= @@max_session_mem_used;
3142+
#
3143+
# On debug build, the usage was
3144+
# - 2.8M without the bug
3145+
# - 1G with the bug.
3146+
set max_session_mem_used=64*1024*1024;
3147+
set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')');
3148+
prepare s from @query;
3149+
# This should not fail with an error:
3150+
execute s;
3151+
id select_type table type possible_keys key key_len ref rows Extra
3152+
1 SIMPLE t2 ALL a NULL NULL NULL 3 Using where
3153+
set max_session_mem_used=@tmp_24117;
3154+
deallocate prepare s;
3155+
drop table t0,t1,t2;
3156+
#
31243157
# MDEV-23811: Both disjunct of WHERE condition contain range conditions
31253158
# for the same index such that the second range condition
31263159
# fully covers the first one. Additionally one of the disjuncts

mysql-test/main/range.test

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,52 @@ set eq_range_index_dive_limit=default;
20922092

20932093
drop table t1;
20942094

2095+
--echo #
2096+
--echo # MDEV-24117: Memory management problem in statistics state...
2097+
--echo # (just the testcase)
2098+
--echo #
2099+
2100+
create table t0(a int);
2101+
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
2102+
2103+
create table t1(a int);
2104+
2105+
# 4K rows
2106+
insert into t1
2107+
select A.a + B.a* 10 + C.a * 100 + D.a * 1000
2108+
from t0 A, t0 B, t0 C, t0 D
2109+
where D.a<4;
2110+
2111+
create table t2 (
2112+
a int,
2113+
b int,
2114+
key(a)
2115+
);
2116+
2117+
insert into t2 values (1,1),(2,2),(3,3);
2118+
2119+
set @query=(select group_concat(a) from t1);
2120+
2121+
set @tmp_24117= @@max_session_mem_used;
2122+
2123+
--echo #
2124+
--echo # On debug build, the usage was
2125+
--echo # - 2.8M without the bug
2126+
--echo # - 1G with the bug.
2127+
2128+
set max_session_mem_used=64*1024*1024;
2129+
2130+
set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')');
2131+
2132+
prepare s from @query;
2133+
2134+
--echo # This should not fail with an error:
2135+
execute s;
2136+
set max_session_mem_used=@tmp_24117;
2137+
2138+
deallocate prepare s;
2139+
2140+
drop table t0,t1,t2;
20952141
--echo #
20962142
--echo # MDEV-23811: Both disjunct of WHERE condition contain range conditions
20972143
--echo # for the same index such that the second range condition

mysql-test/main/range_mrr_icp.result

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,7 @@ SELECT * FROM t1 WHERE
13001300
25 <= a AND b = 23 OR
13011301
23 <= a;
13021302
id select_type table type possible_keys key key_len ref rows Extra
1303-
1 SIMPLE t1 range a a 5 NULL 2 Using where; Using index
1303+
1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index
13041304
SELECT * FROM t1 WHERE
13051305
23 <= a AND a <= 25 OR
13061306
25 <= a AND b = 23 OR
@@ -3110,6 +3110,39 @@ a b
31103110
set eq_range_index_dive_limit=default;
31113111
drop table t1;
31123112
#
3113+
# MDEV-24117: Memory management problem in statistics state...
3114+
# (just the testcase)
3115+
#
3116+
create table t0(a int);
3117+
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
3118+
create table t1(a int);
3119+
insert into t1
3120+
select A.a + B.a* 10 + C.a * 100 + D.a * 1000
3121+
from t0 A, t0 B, t0 C, t0 D
3122+
where D.a<4;
3123+
create table t2 (
3124+
a int,
3125+
b int,
3126+
key(a)
3127+
);
3128+
insert into t2 values (1,1),(2,2),(3,3);
3129+
set @query=(select group_concat(a) from t1);
3130+
set @tmp_24117= @@max_session_mem_used;
3131+
#
3132+
# On debug build, the usage was
3133+
# - 2.8M without the bug
3134+
# - 1G with the bug.
3135+
set max_session_mem_used=64*1024*1024;
3136+
set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')');
3137+
prepare s from @query;
3138+
# This should not fail with an error:
3139+
execute s;
3140+
id select_type table type possible_keys key key_len ref rows Extra
3141+
1 SIMPLE t2 ALL a NULL NULL NULL 3 Using where
3142+
set max_session_mem_used=@tmp_24117;
3143+
deallocate prepare s;
3144+
drop table t0,t1,t2;
3145+
#
31133146
# MDEV-23811: Both disjunct of WHERE condition contain range conditions
31143147
# for the same index such that the second range condition
31153148
# fully covers the first one. Additionally one of the disjuncts

sql/opt_range.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9619,15 +9619,9 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
96199619
}
96209620
bool no_imerge_from_ranges= FALSE;
96219621

9622-
SEL_TREE *rt1= tree1;
9623-
SEL_TREE *rt2= tree2;
96249622
/* Build the range part of the tree for the formula (1) */
96259623
if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys))
96269624
{
9627-
if (no_merges1)
9628-
rt1= new SEL_TREE(tree1, TRUE, param);
9629-
if (no_merges2)
9630-
rt2= new SEL_TREE(tree2, TRUE, param);
96319625
bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys);
96329626
no_imerge_from_ranges= must_be_ored;
96339627

@@ -9685,6 +9679,12 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
96859679
else if (!no_ranges1 && !no_ranges2 && !no_imerge_from_ranges)
96869680
{
96879681
/* Build the imerge part of the tree for the formula (1) */
9682+
SEL_TREE *rt1= tree1;
9683+
SEL_TREE *rt2= tree2;
9684+
if (no_merges1)
9685+
rt1= new SEL_TREE(tree1, TRUE, param);
9686+
if (no_merges2)
9687+
rt2= new SEL_TREE(tree2, TRUE, param);
96889688
if (!rt1 || !rt2 ||
96899689
result->merges.push_back(imerge_from_ranges) ||
96909690
imerge_from_ranges->or_sel_tree(param, rt1) ||
@@ -10350,7 +10350,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
1035010350
if (!tmp->next_key_part)
1035110351
{
1035210352
SEL_ARG *key2_next= key2->next;
10353-
if (key2->use_count)
10353+
if (key2_shared)
1035410354
{
1035510355
SEL_ARG *key2_cpy= new SEL_ARG(*key2);
1035610356
if (!key2_cpy)

sql/sql_prepare.cc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3252,27 +3252,38 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
32523252
void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
32533253
{
32543254
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
3255+
DBUG_ENTER("mysqld_stmt_execute_bulk");
3256+
3257+
const uint packet_header_lenght= 4 + 2; //ID & 2 bytes of flags
3258+
3259+
if (packet_length < packet_header_lenght)
3260+
{
3261+
my_error(ER_MALFORMED_PACKET, MYF(0));
3262+
DBUG_VOID_RETURN;
3263+
}
3264+
32553265
ulong stmt_id= uint4korr(packet);
32563266
uint flags= (uint) uint2korr(packet + 4);
32573267
uchar *packet_end= packet + packet_length;
3258-
DBUG_ENTER("mysqld_stmt_execute_bulk");
32593268

32603269
if (!(thd->client_capabilities &
32613270
MARIADB_CLIENT_STMT_BULK_OPERATIONS))
32623271
{
32633272
DBUG_PRINT("error",
32643273
("An attempt to execute bulk operation without support"));
32653274
my_error(ER_UNSUPPORTED_PS, MYF(0));
3275+
DBUG_VOID_RETURN;
32663276
}
32673277
/* Check for implemented parameters */
32683278
if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES))
32693279
{
32703280
DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags));
32713281
my_error(ER_UNSUPPORTED_PS, MYF(0));
3282+
DBUG_VOID_RETURN;
32723283
}
32733284

32743285
/* stmt id and two bytes of flags */
3275-
packet+= 4 + 2;
3286+
packet+= packet_header_lenght;
32763287
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE,
32773288
(flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES));
32783289
DBUG_VOID_RETURN;
@@ -3349,9 +3360,11 @@ stmt_execute_packet_sanity_check(Prepared_statement *stmt,
33493360
{
33503361
/*
33513362
If there is no parameters, this should be normally already end
3352-
of the packet. If it's not - then error
3363+
of the packet, but it is not a problem if something left (popular
3364+
mistake in protocol implementation) because we will not read anymore
3365+
from the buffer.
33533366
*/
3354-
return (packet_end > packet);
3367+
return false;
33553368
}
33563369
return false;
33573370
}

storage/innobase/trx/trx0rec.cc

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,18 @@ const dtuple_t trx_undo_metadata = {
5353
/*=========== UNDO LOG RECORD CREATION AND DECODING ====================*/
5454

5555
/** Calculate the free space left for extending an undo log record.
56-
@param[in] undo_block undo log page
57-
@param[in] ptr current end of the undo page
56+
@param undo_block undo log page
57+
@param ptr current end of the undo page
5858
@return bytes left */
59-
static ulint trx_undo_left(const buf_block_t* undo_block, const byte* ptr)
59+
static ulint trx_undo_left(const buf_block_t *undo_block, const byte *ptr)
6060
{
61-
/* The 10 is a safety margin, in case we have some small
62-
calculation error below */
63-
return srv_page_size - ulint(ptr - undo_block->frame)
64-
- (10 + FIL_PAGE_DATA_END);
61+
ut_ad(ptr >= &undo_block->frame[TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE]);
62+
ut_ad(ptr <= &undo_block->frame[srv_page_size - 10 - FIL_PAGE_DATA_END]);
63+
64+
/* The 10 is supposed to be an extra safety margin (and needed for
65+
compatibility with older versions) */
66+
return srv_page_size - ulint(ptr - undo_block->frame) -
67+
(10 + FIL_PAGE_DATA_END);
6568
}
6669

6770
/**********************************************************************//**
@@ -133,30 +136,30 @@ trx_undo_log_v_idx(
133136

134137
ut_ad(!vcol->v_indexes.empty());
135138

136-
/* Size to reserve, max 5 bytes for each index id and position, plus
137-
5 bytes for num of indexes, 2 bytes for write total length.
138-
1 byte for undo log record format version marker */
139-
ulint size = 5 + 2 + (first_v_col ? 1 : 0);
139+
ulint size = first_v_col ? 1 + 2 : 2;
140140
const ulint avail = trx_undo_left(undo_block, ptr);
141141

142-
if (avail < size) {
142+
/* The mach_write_compressed(ptr, flen) in
143+
trx_undo_page_report_modify() will consume additional 1 to 5 bytes. */
144+
if (avail < size + 5) {
143145
return(NULL);
144146
}
145147

146-
size = 0;
147148
ulint n_idx = 0;
148149
for (const auto& v_index : vcol->v_indexes) {
149150
n_idx++;
150151
/* FIXME: index->id is 64 bits! */
151152
size += mach_get_compressed_size(uint32_t(v_index.index->id));
152153
size += mach_get_compressed_size(v_index.nth_field);
153154
}
154-
size += 2 + mach_get_compressed_size(n_idx);
155155

156-
if (avail < size) {
156+
size += mach_get_compressed_size(n_idx);
157+
158+
if (avail < size + 5) {
157159
return(NULL);
158160
}
159161

162+
ut_d(const byte* orig_ptr = ptr);
160163

161164
if (first_v_col) {
162165
/* write the version marker */
@@ -179,6 +182,8 @@ trx_undo_log_v_idx(
179182
ptr += mach_write_compressed(ptr, v_index.nth_field);
180183
}
181184

185+
ut_ad(orig_ptr + size == ptr);
186+
182187
mach_write_to_2(old_ptr, ulint(ptr - old_ptr));
183188

184189
return(ptr);
@@ -394,9 +399,6 @@ trx_undo_page_report_insert(
394399
+ undo_block->frame));
395400
byte* ptr = undo_block->frame + first_free;
396401

397-
ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
398-
ut_ad(first_free <= srv_page_size - FIL_PAGE_DATA_END);
399-
400402
if (trx_undo_left(undo_block, ptr) < 2 + 1 + 11 + 11) {
401403
/* Not enough space for writing the general parameters */
402404
return(0);
@@ -803,9 +805,6 @@ trx_undo_page_report_modify(
803805
const uint16_t first_free = mach_read_from_2(ptr_to_first_free);
804806
byte *ptr = undo_block->frame + first_free;
805807

806-
ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
807-
ut_ad(first_free <= srv_page_size - FIL_PAGE_DATA_END);
808-
809808
if (trx_undo_left(undo_block, ptr) < 50) {
810809
/* NOTE: the value 50 must be big enough so that the general
811810
fields written below fit on the undo log page */

tests/mysql_client_test.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21076,8 +21076,11 @@ static void test_mdev19838()
2107621076
" VALUES "
2107721077
"(0x1111111111111111)", -1);
2107821078

21079-
/* Expecting an error if parameters are sent */
21080-
DIE_UNLESS(rc != 0 || paramCount == 0);
21079+
/*
21080+
We allow junk at the end of the packet in case of
21081+
no parameters. So it will succeed.
21082+
*/
21083+
DIE_UNLESS(rc == 0);
2108121084
}
2108221085

2108321086
mysql_stmt_close(stmt);

0 commit comments

Comments
 (0)