summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gshchepa/uchum@gleb.loc>2007-10-26 21:26:06 +0500
committerunknown <gshchepa/uchum@gleb.loc>2007-10-26 21:26:06 +0500
commitb9ecbb7e5c764158b81597b4197a926732c31004 (patch)
treec5fb7ca84eb605614b54e556b4845137df4d556a
parent6356f16196be6492f7b18cc06df53075a2b14203 (diff)
downloadmariadb-git-b9ecbb7e5c764158b81597b4197a926732c31004.tar.gz
Fixed bug #31036: Using order by with archive table crashes server.
1. Memory overrun have been fixed. 2. Server failure on assertion has been fixed. storage/archive/azio.c: Fixed bug #31036. The ha_archive::rnd_pos function has been modified to take into account the result of the azseek function and to return HA_ERR_CRASHED_ON_USAGE in case of seek error. storage/archive/ha_archive.cc: Fixed bug #31036. 1. Memory overrun has been fixed: maximal sizes of azio_stream::inbuf and azio_stream::outbuf was mixed. 2. Zero value of the output parameter of the azread function was incorrectly interpreted by the azseek function: after the first successful read attempt the execution of the azseek loop was interrupted and negative value was returned. (See ha_archive::rnd_pos: that negative value was silently ignored, and an incomplete data was used, for example, as a size of a packed record, and server failed with the assertion: "row_len <= record_buffer->length".) mysql-test/t/archive.test: Added test case for bug #31036. mysql-test/r/archive.result: Added test case for bug #31036.
-rw-r--r--mysql-test/r/archive.result4
-rw-r--r--mysql-test/t/archive.test22
-rw-r--r--storage/archive/azio.c10
-rw-r--r--storage/archive/ha_archive.cc4
4 files changed, 33 insertions, 7 deletions
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 36b013703d8..803c102f6cf 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -12682,3 +12682,7 @@ check table t1 extended;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+CREATE TABLE t1(a VARCHAR(510)) ENGINE = ARCHIVE;
+INSERT INTO t1(a) VALUES ('');
+SELECT * FROM t1 ORDER BY a;
+DROP TABLE t1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index 23c591856a7..a8567ab9fd0 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1559,3 +1559,25 @@ insert into t1 set a='';
insert into t1 set a='a';
check table t1 extended;
drop table t1;
+
+#
+# BUG#31036 - Using order by with archive table crashes server
+#
+
+CREATE TABLE t1(a VARCHAR(510)) ENGINE = ARCHIVE;
+
+let $bug31036=41;
+--disable_query_log
+while($bug31036)
+{
+ INSERT INTO t1(a) VALUES (REPEAT('a', 510));
+ dec $bug31036;
+}
+--enable_query_log
+INSERT INTO t1(a) VALUES ('');
+
+--disable_result_log
+SELECT * FROM t1 ORDER BY a;
+--enable_result_log
+
+DROP TABLE t1;
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index f6b1a6e733f..b5c3dd465af 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -681,8 +681,8 @@ my_off_t azseek (s, offset, whence)
/* There was a zmemzero here if inbuf was null -Brian */
while (offset > 0)
{
- uInt size = AZ_BUFSIZE_WRITE;
- if (offset < AZ_BUFSIZE_WRITE) size = (uInt)offset;
+ uInt size = AZ_BUFSIZE_READ;
+ if (offset < AZ_BUFSIZE_READ) size = (uInt)offset;
size = azwrite(s, s->inbuf, size);
if (size == 0) return -1L;
@@ -725,11 +725,11 @@ my_off_t azseek (s, offset, whence)
}
while (offset > 0) {
int error;
- unsigned int size = AZ_BUFSIZE_READ;
- if (offset < AZ_BUFSIZE_READ) size = (int)offset;
+ unsigned int size = AZ_BUFSIZE_WRITE;
+ if (offset < AZ_BUFSIZE_WRITE) size = (int)offset;
size = azread(s, s->outbuf, size, &error);
- if (error <= 0) return -1L;
+ if (error < 0) return -1L;
offset -= size;
}
return s->out;
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 6696eac2fbb..3015ae78761 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1241,8 +1241,8 @@ int ha_archive::rnd_pos(uchar * buf, uchar *pos)
DBUG_ENTER("ha_archive::rnd_pos");
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
current_position= (my_off_t)my_get_ptr(pos, ref_length);
- (void)azseek(&archive, current_position, SEEK_SET);
-
+ if (azseek(&archive, current_position, SEEK_SET) < 0)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
DBUG_RETURN(get_row(&archive, buf));
}