From b83b4697d229c78d85954b219cfed5caf428b20e Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 27 Jun 2008 20:56:41 +0500 Subject: [PATCH] backport from 6.0 Bug#35658 (An empty binary value leads to mysqld crash) Before this fix, the following token b'' caused the parser to crash when reading the binary value from the empty string. The crash was caused by: ptr+= max_length - 1; because max_length is unsigned and was 0, causing an overflow. With this fix, an empty binary literal b'' is parsed as a binary value 0, in Item_bin_string. mysql-test/r/varbinary.result: Bug#35658 (An empty binary value leads to mysqld crash) mysql-test/t/varbinary.test: Bug#35658 (An empty binary value leads to mysqld crash) sql/item.cc: Bug#35658 (An empty binary value leads to mysqld crash) --- mysql-test/r/varbinary.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/varbinary.test | 28 ++++++++++++++++++++++++++++ sql/item.cc | 29 ++++++++++++++++++----------- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index a41885a257d..f584c22f98a 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -78,3 +78,34 @@ alter table t1 modify a varchar(255); select length(a) from t1; length(a) 6 +select 0b01000001; +0b01000001 +A +select 0x41; +0x41 +A +select b'01000001'; +b'01000001' +A +select x'41', 0+x'41'; +x'41' 0+x'41' +A 65 +select N'abc', length(N'abc'); +abc length(N'abc') +abc 3 +select N'', length(N''); + length(N'') + 0 +select '', length(''); + length('') + 0 +select b'', 0+b''; +b'' 0+b'' + 0 +select x'', 0+x''; +x'' 0+x'' + 0 +select 0x; +ERROR 42S22: Unknown column '0x' in 'field list' +select 0b; +ERROR 42S22: Unknown column '0b' in 'field list' diff --git a/mysql-test/t/varbinary.test b/mysql-test/t/varbinary.test index 2f0c1c83e84..427c1a6b84a 100644 --- a/mysql-test/t/varbinary.test +++ b/mysql-test/t/varbinary.test @@ -84,3 +84,31 @@ select length(a) from t1; alter table t1 modify a varchar(255); select length(a) from t1; +# +# Bug#35658 (An empty binary value leads to mysqld crash) +# + +select 0b01000001; + +select 0x41; + +select b'01000001'; + +select x'41', 0+x'41'; + +select N'abc', length(N'abc'); + +select N'', length(N''); + +select '', length(''); + +select b'', 0+b''; + +select x'', 0+x''; + +--error ER_BAD_FIELD_ERROR +select 0x; + +--error ER_BAD_FIELD_ERROR +select 0b; + diff --git a/sql/item.cc b/sql/item.cc index 9ff1f8c0084..bf447581afa 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5013,21 +5013,28 @@ Item_bin_string::Item_bin_string(const char *str, uint str_length) if (!ptr) return; str_value.set(ptr, max_length, &my_charset_bin); - ptr+= max_length - 1; - ptr[1]= 0; // Set end null for string - for (; end >= str; end--) + + if (max_length > 0) { - if (power == 256) + ptr+= max_length - 1; + ptr[1]= 0; // Set end null for string + for (; end >= str; end--) { - power= 1; - *ptr--= bits; - bits= 0; + if (power == 256) + { + power= 1; + *ptr--= bits; + bits= 0; + } + if (*end == '1') + bits|= power; + power<<= 1; } - if (*end == '1') - bits|= power; - power<<= 1; + *ptr= (char) bits; } - *ptr= (char) bits; + else + ptr[0]= 0; + collation.set(&my_charset_bin, DERIVATION_COERCIBLE); fixed= 1; }