Incorrect blob_length of size ~ 4GB that is a result of substracting incorrect record lenghts and overflow
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
MariaDB |
Fix Released
|
High
|
Igor Babaev |
Bug Description
The following test case extracted from subselect.test, results in the
allocation of a 4 GB memory buffer for JOIN_CACHE. This huge buffer
is allocated because of subtracting bigger record length from a smaller
one, then assigning to a UINT. The resulting negative value overflows
and results in a very big positive number.
Test case:
CREATE TABLE t1 (
categoryId int(11) NOT NULL,
courseId int(11) NOT NULL,
startDate datetime NOT NULL,
endDate datetime NOT NULL,
createDate datetime NOT NULL,
modifyDate timestamp NOT NULL,
attributes text NOT NULL
);
INSERT INTO t1 VALUES (1,41,'
(1,86,'
(1,87,'
(2,52,'
(2,53,'
(2,88,'
(2,89,'
(3,51,'
(5,12,'
CREATE TABLE t2 (
userId int(11) NOT NULL,
courseId int(11) NOT NULL,
date datetime NOT NULL
);
INSERT INTO t2 VALUES (5141,71,
(5141,72,
(5141,52,
(5141,12,
(5141,87,
(5141,89,
CREATE TABLE t3 (
groupId int(11) NOT NULL,
parentId int(11) NOT NULL,
startDate datetime NOT NULL,
endDate datetime NOT NULL,
createDate datetime NOT NULL,
modifyDate timestamp NOT NULL,
ordering int(11)
);
INSERT INTO t3 VALUES (12,9,'
CREATE TABLE t4 (
id int(11) NOT NULL,
groupTypeId int(11) NOT NULL,
groupKey varchar(50) NOT NULL,
name text,
ordering int(11),
description text,
createDate datetime NOT NULL,
modifyDate timestamp NOT NULL
);
INSERT INTO t4 VALUES (9,5,'stationer
(12,5,'
CREATE TABLE t5 (
userId int(11) NOT NULL,
groupId int(11) NOT NULL,
createDate datetime NOT NULL,
modifyDate timestamp NOT NULL
);
INSERT INTO t5 VALUES (5141,12,
select
count(distinct t2.userid) pass,
groupstuff.*,
count(
t1.categoryid,
t2.courseid,
date_format(date, '%b%y') as colhead
from t2
join t1 on t2.courseid=
join
(
select
t5.userid,
parentid,
parentgroup,
childid,
groupname,
grouptypeid
from t5
join
(
select t4.id as parentid,
t4.name as parentgroup,
t4.id as childid,
t4.name as groupname,
from t4
) as gin on t5.groupid=
) as groupstuff on t2.userid = groupstuff.userid
group by
groupstuff.
Changed in maria: | |
milestone: | none → 5.3 |
assignee: | nobody → Igor Babaev (igorb-seattle) |
importance: | Undecided → High |
status: | New → Confirmed |
Changed in maria: | |
status: | Confirmed → In Progress |
Changed in maria: | |
status: | In Progress → Fix Committed |
Changed in maria: | |
status: | Fix Committed → Fix Released |
I traced the problem to the following code:
Breakpoint 1, st_join_ table:: calc_used_ field_length (this=0x17e1df68, max_fl=true) at sql_select.cc:6527 >s->reclength- rec_length) ); >file-> stats.mean_ rec_length- >s->reclength- rec_length) ); fieldlength= rec_length; file->stats. mean_rec_ length
6527 (table-
(gdb) list
6522 {
6523 // TODO: to improve this estimate for max expected length
6524 if (blobs)
6525 {
6526 uint blob_length=(uint) (table-
6527 (table-
6528 rec_length+=(uint) max(sizeof(void*) * blobs, blob_length);
6529 }
6530 max_used_
6531 }
(gdb) p table->
$1 = 54
(gdb) p table->s->reclength
$2 = 96
(gdb) p rec_length
$3 = 19
(gdb) n
6528 rec_length+=(uint) max(sizeof(void*) * blobs, blob_length);
(gdb) p blob_length
$4 = 4294967273
Above: blob_length = (uint) 54 - 77
Verified on two different machines - Ubuntu 11.04 64-bit, and 64-bit CentOS.