Commit 2a76abce authored by unknown's avatar unknown

Fix for bug #29353: inserting a negative value to a csv table leads to the table corruption

Problem: we believe a number cannot start with '-' ['+'] sign reading rows.

Fix: let field->store() check given values.


mysql-test/r/csv.result:
  Fix for bug #29353: inserting a negative value to a csv table leads to the table corruption
    - test result.
mysql-test/t/csv.test:
  Fix for bug #29353: inserting a negative value to a csv table leads to the table corruption
    - test case.
storage/csv/ha_tina.cc:
  Fix for bug #29353: inserting a negative value to a csv table leads to the table corruption
    - code optimization: removed unnecessary file_buff->get_value() calls.
    - let field->store() check given value correctness.
parent 0314c73a
......@@ -5261,3 +5261,34 @@ CREATE TABLE `bug21328` (
insert into bug21328 values (1,NULL,NULL);
alter table bug21328 engine=myisam;
drop table bug21328;
create table t1(a int) engine=csv;
insert into t1 values(-1), (-123.34), (2), (-23);
select * from t1;
a
-1
-123
2
-23
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
create table t1(a int, b int) engine=csv;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair Warning Data truncated for column 'a' at row 1
test.t1 repair status OK
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
select * from t1;
a b
1 0
-200 1
-1 -1
-1 -100
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
End of 5.1 tests
......@@ -1674,3 +1674,28 @@ CREATE TABLE `bug21328` (
insert into bug21328 values (1,NULL,NULL);
alter table bug21328 engine=myisam;
drop table bug21328;
#
# Bug #29353: negative values
#
create table t1(a int) engine=csv;
insert into t1 values(-1), (-123.34), (2), (-23);
select * from t1;
check table t1;
drop table t1;
create table t1(a int, b int) engine=csv;
--write_file $MYSQLTEST_VARDIR/master-data/test/t1.CSV
1, 1E-2
-2E2, .9
-10E-1, -.9
-1, -100.1
1a, -2b
EOF
repair table t1;
check table t1;
select * from t1;
check table t1;
drop table t1;
--echo End of 5.1 tests
......@@ -45,11 +45,12 @@
#pragma implementation // gcc: Class implementation
#endif
#include "mysql_priv.h"
#define MYSQL_SERVER 1
#include "mysql_priv.h"
#include <mysql/plugin.h>
#include "ha_tina.h"
#include <mysql/plugin.h>
/*
uchar + uchar + ulonglong + ulonglong + ulonglong + ulonglong + uchar
......@@ -609,37 +610,41 @@ int ha_tina::find_current_row(uchar *buf)
for (Field **field=table->field ; *field ; field++)
{
char curr_char;
buffer.length(0);
if (curr_offset < end_offset &&
file_buff->get_value(curr_offset) == '"')
if (curr_offset >= end_offset)
goto err;
curr_char= file_buff->get_value(curr_offset);
if (curr_char == '"')
{
curr_offset++; // Incrementpast the first quote
for(;curr_offset < end_offset; curr_offset++)
for(; curr_offset < end_offset; curr_offset++)
{
curr_char= file_buff->get_value(curr_offset);
// Need to convert line feeds!
if (file_buff->get_value(curr_offset) == '"' &&
((file_buff->get_value(curr_offset + 1) == ',') ||
(curr_offset == end_offset -1 )))
if (curr_char == '"' &&
(curr_offset == end_offset - 1 ||
file_buff->get_value(curr_offset + 1) == ','))
{
curr_offset+= 2; // Move past the , and the "
break;
}
if (file_buff->get_value(curr_offset) == '\\' &&
curr_offset != (end_offset - 1))
if (curr_char == '\\' && curr_offset != (end_offset - 1))
{
curr_offset++;
if (file_buff->get_value(curr_offset) == 'r')
curr_char= file_buff->get_value(curr_offset);
if (curr_char == 'r')
buffer.append('\r');
else if (file_buff->get_value(curr_offset) == 'n' )
else if (curr_char == 'n' )
buffer.append('\n');
else if ((file_buff->get_value(curr_offset) == '\\') ||
(file_buff->get_value(curr_offset) == '"'))
buffer.append(file_buff->get_value(curr_offset));
else if (curr_char == '\\' || curr_char == '"')
buffer.append(curr_char);
else /* This could only happed with an externally created file */
{
buffer.append('\\');
buffer.append(file_buff->get_value(curr_offset));
buffer.append(curr_char);
}
}
else // ordinary symbol
......@@ -650,36 +655,29 @@ int ha_tina::find_current_row(uchar *buf)
*/
if (curr_offset == end_offset - 1)
goto err;
buffer.append(file_buff->get_value(curr_offset));
buffer.append(curr_char);
}
}
}
else if (my_isdigit(system_charset_info,
file_buff->get_value(curr_offset)))
else
{
for(;curr_offset < end_offset; curr_offset++)
for(; curr_offset < end_offset; curr_offset++)
{
if (file_buff->get_value(curr_offset) == ',')
curr_char= file_buff->get_value(curr_offset);
if (curr_char == ',')
{
curr_offset+= 1; // Move past the ,
curr_offset++; // Skip the ,
break;
}
if (my_isdigit(system_charset_info, file_buff->get_value(curr_offset)))
buffer.append(file_buff->get_value(curr_offset));
else if (file_buff->get_value(curr_offset) == '.')
buffer.append(file_buff->get_value(curr_offset));
else
goto err;
buffer.append(curr_char);
}
}
else
if (bitmap_is_set(table->read_set, (*field)->field_index))
{
if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset()))
goto err;
}
if (bitmap_is_set(table->read_set, (*field)->field_index))
(*field)->store(buffer.ptr(), buffer.length(), buffer.charset());
}
next_position= end_offset + eoln_len;
error= 0;
......@@ -1004,6 +1002,7 @@ int ha_tina::delete_row(const uchar * buf)
int ha_tina::rnd_init(bool scan)
{
THD *thd= table ? table->in_use : current_thd;
DBUG_ENTER("ha_tina::rnd_init");
/* set buffer to the beginning of the file */
......@@ -1015,6 +1014,7 @@ int ha_tina::rnd_init(bool scan)
stats.records= 0;
records_is_known= 0;
chain_ptr= chain;
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values
DBUG_RETURN(0);
}
......@@ -1298,6 +1298,7 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
current_position= next_position= 0;
/* Read the file row-by-row. If everything is ok, repair is not needed. */
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values
while (!(rc= find_current_row(buf)))
{
rows_repaired++;
......@@ -1463,6 +1464,7 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
/* set current position to the beginning of the file */
current_position= next_position= 0;
/* Read the file row-by-row. If everything is ok, repair is not needed. */
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values
while (!(rc= find_current_row(buf)))
{
count--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment