diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index f3522e05380..d86ae6c7961 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -1,6 +1,6 @@ drop table if exists t1; -select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); -row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) +select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3)); +(1,2,3) IN ((3,2,3), (1,2,3), (1,3,3)) 1 select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) @@ -32,14 +32,23 @@ NULL select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3)); row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3)) 0 -select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4))); -row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4))) +select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))); +(1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))) 1 select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4)); Cardinality error (more/less than 2 columns) select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))) NULL +SELECT (1,2,3)=(0,NULL,3); +(1,2,3)=(0,NULL,3) +0 +SELECT (1,2,3)=(1,NULL,3); +(1,2,3)=(1,NULL,3) +NULL +SELECT (1,2,3)=(1,NULL,0); +(1,2,3)=(1,NULL,0) +NULL SELECT ROW(1,2,3)=ROW(1,2,3); ROW(1,2,3)=ROW(1,2,3) 1 @@ -132,4 +141,6 @@ select 1 from t1 where ROW(1,1); Cardinality error (more/less than 1 columns) select count(*) from t1 order by ROW(1,1); Cardinality error (more/less than 1 columns) +select count(*) from t1 having (1,1) order by i; +Cardinality error (more/less than 1 columns) drop table t1; diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 099eaa95c77..98fd640f12e 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -3,7 +3,7 @@ drop table if exists t1; --enable_warnings -select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); +select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3)); select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)); select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)); @@ -14,11 +14,16 @@ select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3)); select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3)); -select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4))); +select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))); -- error 1239 select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4)); select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); +SELECT (1,2,3)=(0,NULL,3); +SELECT (1,2,3)=(1,NULL,3); +# here's something for Sanja to fix :) +SELECT (1,2,3)=(1,NULL,0); + SELECT ROW(1,2,3)=ROW(1,2,3); SELECT ROW(2,2,3)=ROW(1+1,2,3); SELECT ROW(1,2,3)=ROW(1+1,2,3); @@ -58,9 +63,7 @@ create table t1 (i int); select 1 from t1 where ROW(1,1); -- error 1239 select count(*) from t1 order by ROW(1,1); -#TODO remove comments after parser fixing -#-- error 1239 -#select count(*) from t1 order by i having (1,1); -#-- error 1239 -#select 1 from t1 limit (1,1), (1,1); +-- error 1239 +select count(*) from t1 having (1,1) order by i; drop table t1; + diff --git a/sql/field.cc b/sql/field.cc index 00bb409e82e..0fa306fe718 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1652,11 +1652,10 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) long tmp; int error= 0; char *end; - /* TODO: Make multi-byte-character safe */ - while (len && my_isspace(cs,*from)) - { - len--; from++; - } + + tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES); + len-= tmp; + from+= tmp; my_errno=0; if (unsigned_flag) { @@ -1910,11 +1909,10 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) longlong tmp; int error= 0; char *end; - /* TODO: Make multi byte safe */ - while (len && my_isspace(cs,*from)) - { // For easy error check - len--; from++; - } + + tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES); + len-= tmp; + from+= tmp; my_errno=0; if (unsigned_flag) { @@ -3878,14 +3876,6 @@ void Field_datetime::sql_type(String &res) const int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; -#ifdef USE_TIS620 - if (!binary()) { - ThNormalize((uchar *)ptr, field_length, (uchar *)from, length); - if (length < field_length) { - bfill(ptr + length, field_length - length, ' '); - } - } -#else if (length <= field_length) { memcpy(ptr,from,length); @@ -3909,7 +3899,6 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) } } } -#endif /* USE_TIS620 */ return error; } @@ -4062,12 +4051,6 @@ uint Field_string::max_packed_col_length(uint max_length) int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; -#ifdef USE_TIS620 - if (!binary()) - { - ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length); - } -#else if (length > field_length) { length=field_length; @@ -4075,7 +4058,6 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) error= 1; } memcpy(ptr+2,from,length); -#endif /* USE_TIS620 */ int2store(ptr, length); return error; } @@ -4376,28 +4358,11 @@ int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs) } else { -#ifdef USE_TIS620 - char *th_ptr=0; -#endif Field_blob::store_length(len); if (table->copy_blobs || len <= MAX_FIELD_WIDTH) { // Must make a copy -#ifdef USE_TIS620 - if (!binary()) - { - /* If there isn't enough memory, use original string */ - if ((th_ptr=(char * ) my_malloc(sizeof(char) * len,MYF(0)))) - { - ThNormalize((uchar *) th_ptr, len, (uchar *) from, len); - from= (const char*) th_ptr; - } - } -#endif /* USE_TIS620 */ value.copy(from,len,charset()); from=value.ptr(); -#ifdef USE_TIS620 - my_free(th_ptr,MYF(MY_ALLOW_ZERO_PTR)); -#endif } bmove(ptr+packlength,(char*) &from,sizeof(char*)); } diff --git a/sql/item.h b/sql/item.h index 25cc2601281..3852a63e722 100644 --- a/sql/item.h +++ b/sql/item.h @@ -580,12 +580,12 @@ public: #include "spatial.h" #include "item_sum.h" #include "item_func.h" +#include "item_row.h" #include "item_cmpfunc.h" #include "item_strfunc.h" #include "item_timefunc.h" #include "item_uniq.h" #include "item_subselect.h" -#include "item_row.h" class Item_copy_string :public Item { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1c579708503..06b7dc451dc 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -392,51 +392,44 @@ longlong Item_func_strcmp::val_int() return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1); } - void Item_func_interval::fix_length_and_dec() { - bool nums=1; - uint i; - for (i=0 ; i < arg_count ; i++) + if (row->cols() > 8) { - if (!args[i]) - return; // End of memory - if (args[i]->type() != Item::INT_ITEM && - args[i]->type() != Item::REAL_ITEM) + bool consts=1; + + for (uint i=1 ; consts && i < row->cols() ; i++) { - nums=0; - break; + consts&= row->el(i)->const_item(); } - } - if (nums && arg_count >= 8) - { - if ((intervals=(double*) sql_alloc(sizeof(double)*arg_count))) + + if (consts && + (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1)))) { - for (i=0 ; i < arg_count ; i++) - intervals[i]=args[i]->val(); + for (uint i=1 ; i < row->cols(); i++) + intervals[i-1]=row->el(i)->val(); } } maybe_null= 0; max_length= 2; - used_tables_cache|=item->used_tables(); } /* return -1 if null value, 0 if lower than lowest - 1 - arg_count if between args[n] and args[n+1] - arg_count+1 if higher than biggest argument + 1 - arg_count-1 if between args[n] and args[n+1] + arg_count if higher than biggest argument */ longlong Item_func_interval::val_int() { - double value=item->val(); - if (item->null_value) - return -1; // -1 if null /* purecov: inspected */ + double value=row->el(0)->val(); + if (row->el(0)->null_value) + return -1; // -1 if null if (intervals) { // Use binary search to find interval uint start,end; - start=0; end=arg_count-1; + start=1; end=row->cols()-2; while (start != end) { uint mid=(start+end+1)/2; @@ -447,31 +440,14 @@ longlong Item_func_interval::val_int() } return (value < intervals[start]) ? 0 : start+1; } - if (args[0]->val() > value) - return 0; - for (uint i=1 ; i < arg_count ; i++) + + uint i; + for (i=1 ; i < row->cols() ; i++) { - if (args[i]->val() > value) - return i; + if (row->el(i)->val() > value) + return i-1; } - return (longlong) arg_count; -} - - -void Item_func_interval::update_used_tables() -{ - Item_func::update_used_tables(); - item->update_used_tables(); - used_tables_cache|=item->used_tables(); - const_item_cache&=item->const_item(); -} - -bool Item_func_interval::check_loop(uint id) -{ - DBUG_ENTER("Item_func_interval::check_loop"); - if (Item_func::check_loop(id)) - DBUG_RETURN(1); - DBUG_RETURN(item->check_loop(id)); + return i-1; } void Item_func_between::fix_length_and_dec() diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8641ab410b3..1bb85a9e233 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -267,27 +267,14 @@ public: class Item_func_interval :public Item_int_func { - Item *item; + Item_row *row; double *intervals; public: - Item_func_interval(Item *a,List &list) - :Item_int_func(list),item(a),intervals(0) {} + Item_func_interval(Item_row *a) + :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); } longlong val_int(); - bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) - { - return (item->fix_fields(thd, tlist, &item) || item->check_cols(1) || - Item_func::fix_fields(thd, tlist, ref)); - } void fix_length_and_dec(); - ~Item_func_interval() { delete item; } const char *func_name() const { return "interval"; } - void update_used_tables(); - bool check_loop(uint id); - void set_outer_resolving() - { - item->set_outer_resolving(); - Item_func::set_outer_resolving(); - } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 66f0510cc3d..03dd940db51 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2014,9 +2014,8 @@ String *Item_func_conv_charset::val_str(String *str) d0=d=(unsigned char*)str->ptr(); de=d+dmaxlen; - while (s < se && d < de) + while (1) { - cnvres=from->mb_wc(from,&wc,s,se); if (cnvres>0) { @@ -2089,8 +2088,8 @@ String *Item_func_conv_charset3::val_str(String *str) d0=d=(unsigned char*)str->ptr(); de=d+dmaxlen; - while (s < se && d < de){ - + while (1) + { cnvres=from_charset->mb_wc(from_charset,&wc,s,se); if (cnvres>0) { diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 0d604d043cc..654076c3f41 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -706,7 +706,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, char *to_start= to; uchar *to_end= (uchar*) to+to_length; - while ((uchar*) from < from_end) + while (1) { if ((cnvres=from_cs->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) from+= cnvres; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d603748c443..d3092d8ca62 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr - using_list expr_or_default set_expr_or_default + using_list expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init exists_subselect exists_subselect_init @@ -1928,10 +1928,10 @@ expr_expr: | expr '^' expr { $$= new Item_func_bit_xor($1,$3); } | expr '&' expr { $$= new Item_func_bit_and($1,$3); } | expr '%' expr { $$= new Item_func_mod($1,$3); } - | expr '+' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,0); } - | expr '-' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,1); } + | expr '+' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,0); } + | expr '-' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,1); } | expr COLLATE_SYM collation_name { $$= new Item_func_set_collation($1,$3); }; @@ -1975,10 +1975,10 @@ no_in_expr: | no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); } | no_in_expr '%' expr { $$= new Item_func_mod($1,$3); } | no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } - | no_in_expr '+' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,0); } - | no_in_expr '-' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,1); } + | no_in_expr '+' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,0); } + | no_in_expr '-' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,1); } | simple_expr; /* expressions that begin with 'expr' that does NOT follow AND */ @@ -2030,12 +2030,16 @@ no_and_expr: | no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); } | no_and_expr '%' expr { $$= new Item_func_mod($1,$3); } | no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } - | no_and_expr '+' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,0); } - | no_and_expr '-' INTERVAL_SYM expr interval - { $$= new Item_date_add_interval($1,$4,$5,1); } + | no_and_expr '+' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,0); } + | no_and_expr '-' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,1); } | simple_expr; +interval_expr: + INTERVAL_SYM expr { $$=$2; } + ; + simple_expr: simple_ident | literal @@ -2061,8 +2065,11 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } - /* Note: In SQL-99 "ROW" is optional, but not having it mandatory - causes conflicts with the INTERVAL syntax. */ + | '(' expr ',' expr_list ')' + { + $4->push_front($2); + $$= new Item_row(*$4); + } | ROW_SYM '(' expr ',' expr_list ')' { $5->push_front($3); @@ -2118,10 +2125,10 @@ simple_expr: $$= new Item_func_curtime($3); Lex->safe_to_cache_query=0; } - | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3,$6,$7,0); } - | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3,$6,$7,1); } + | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' + { $$= new Item_date_add_interval($3,$5,$6,0); } + | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' + { $$= new Item_date_add_interval($3,$5,$6,1); } | DATABASE '(' ')' { $$= new Item_func_database(); @@ -2181,14 +2188,21 @@ simple_expr: { $$= new Item_func_if($3,$5,$7); } | INSERT '(' expr ',' expr ',' expr ',' expr ')' { $$= new Item_func_insert($3,$5,$7,$9); } - | INTERVAL_SYM expr interval '+' expr + | interval_expr interval '+' expr /* we cannot put interval before - */ - { $$= new Item_date_add_interval($5,$2,$3,0); } - | INTERVAL_SYM '(' expr ',' expr_list ')' - { $$= new Item_func_interval($3,* $5); } + { $$= new Item_date_add_interval($4,$1,$2,0); } + | interval_expr + { + if ($1->type() != Item::ROW_ITEM) + { + send_error(Lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + $$= new Item_func_interval((Item_row *)$1); + } | LAST_INSERT_ID '(' ')' { - $$= get_system_var(OPT_SESSION, "last_insert_id", 14, + $$= get_system_var(OPT_SESSION, "last_insert_id", 14, "last_insert_id()"); } | LAST_INSERT_ID '(' expr ')' @@ -2243,10 +2257,10 @@ simple_expr: | MPOLYFROMTEXT '(' expr ',' expr ')' { $$= new Item_func_geometry_from_text($3); } | MULTIPOINT '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, + { $$= new Item_func_spatial_collection(* $3, Geometry::wkbMultiPoint, Geometry::wkbPoint); } | MULTIPOLYGON '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, + { $$= new Item_func_spatial_collection(* $3, Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); } | NOW_SYM optional_braces { $$= new Item_func_now(); Lex->safe_to_cache_query=0;} @@ -2265,7 +2279,7 @@ simple_expr: | POLYFROMTEXT '(' expr ',' expr ')' { $$= new Item_func_geometry_from_text($3); } | POLYGON '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, + { $$= new Item_func_spatial_collection(* $3, Geometry::wkbPolygon, Geometry::wkbLineString); } | POSITION_SYM '(' no_in_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } @@ -2425,7 +2439,7 @@ in_sum_expr: }; cast_type: - BINARY { $$=ITEM_CAST_BINARY; } + BINARY { $$=ITEM_CAST_BINARY; } | CHAR_SYM { $$=ITEM_CAST_CHAR; } | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } @@ -4647,7 +4661,7 @@ subselect_start: '(' SELECT_SYM { LEX *lex=Lex; - if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN && + if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN && lex->sql_command <= (int)SQLCOM_HA_READ) || lex->sql_command == (int)SQLCOM_KILL) { send_error(lex->thd, ER_SYNTAX_ERROR); YYABORT; diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index a475a36d049..37bf2aba509 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6175,6 +6175,9 @@ my_wc_mb_big5(CHARSET_INFO *cs __attribute__((unused)), int code; + if (s >= e) + return MY_CS_TOOSMALL; + if(wc<0x80) { s[0]=wc; @@ -6200,6 +6203,9 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), int hi=s[0]; + if (s >= e) + return MY_CS_TOOFEW(0); + if(hi<0x80) { pwc[0]=hi; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index de137377c65..48d5536a2cb 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -96,6 +96,9 @@ static int my_mb_wc_bin(CHARSET_INFO *cs __attribute__((unused)), const unsigned char *str, const unsigned char *end __attribute__((unused))) { + if (str >= end) + return MY_CS_TOOFEW(0); + *wc=str[0]; return 1; } @@ -105,6 +108,9 @@ static int my_wc_mb_bin(CHARSET_INFO *cs __attribute__((unused)), unsigned char *s, unsigned char *e __attribute__((unused))) { + if (s >= e) + return MY_CS_TOOSMALL; + if (wc < 256) { s[0]= (char) wc; diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index ee75673e1c5..d4eebdcb4a9 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8593,6 +8593,9 @@ my_wc_mb_euc_kr(CHARSET_INFO *cs __attribute__((unused)), { int code; + if (s >= e) + return MY_CS_TOOSMALL; + if (wc<0x80) { s[0]=wc; @@ -8618,6 +8621,9 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), int hi=s[0]; + if (s >= e) + return MY_CS_TOOFEW(0); + if (hi<0x80) { pwc[0]=hi; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 0820d03b2d0..b01053866be 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5643,6 +5643,9 @@ my_wc_mb_gb2312(CHARSET_INFO *cs __attribute__((unused)), { int code; + if (s >= e) + return MY_CS_TOOSMALL; + if (wc<0x80) { s[0]=wc; @@ -5668,6 +5671,9 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), hi=s[0]; + if (s >= e) + return MY_CS_TOOFEW(0); + if(hi<0x80) { pwc[0]=hi; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 3aff098cd14..c65c9f2123e 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9829,6 +9829,9 @@ my_wc_mb_gbk(CHARSET_INFO *cs __attribute__((unused)), { int code; + if (s >= e) + return MY_CS_TOOSMALL; + if (wc<0x80) { s[0]=wc; @@ -9852,6 +9855,9 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), { int hi; + if (s >= e) + return MY_CS_TOOFEW(0); + hi=s[0]; if (hi<0x80) diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 99d03e187b1..e028a027484 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -106,6 +106,9 @@ int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const unsigned char *str, const unsigned char *end __attribute__((unused))) { + if (str >= end) + return MY_CS_TOOFEW(0); + *wc=cs->tab_to_uni[*str]; return (!wc[0] && str[0]) ? MY_CS_ILSEQ : 1; } @@ -116,6 +119,9 @@ int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, { MY_UNI_IDX *idx; + if (str >= end) + return MY_CS_TOOSMALL; + for (idx=cs->tab_from_uni; idx->tab ; idx++) { if (idx->from <= wc && idx->to >= wc) diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index b19bcf1a45a..0408332ee30 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4420,6 +4420,9 @@ my_wc_mb_sjis(CHARSET_INFO *cs __attribute__((unused)), { int code; + if (s >= e) + return MY_CS_TOOSMALL; + if(wc<0x80) { s[0]=wc; @@ -4442,6 +4445,9 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)), my_wc_t *pwc, const uchar *s, const uchar *e){ int hi=s[0]; + if (s >= e) + return MY_CS_TOOFEW(0); + if(hi<0x80) { pwc[0]=hi; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 12e177a89be..211b42db470 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8350,6 +8350,9 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e) unsigned char buf[2]; unsigned char c1; int ret,jp; + + if (s >= e) + return MY_CS_TOOSMALL; if (wc<0x80) { diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index a237b6f14a0..3f859223a15 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1586,6 +1586,9 @@ static int my_utf8_uni (CHARSET_INFO *cs __attribute__((unused)) , { unsigned char c = s[0]; + if (s >= e) + return MY_CS_TOOFEW(0); + if (c < 0x80) { *pwc = c; @@ -1688,6 +1691,9 @@ static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) , { int count; + if (r >= e) + return MY_CS_TOOSMALL; + if (wc < 0x80) count = 1; else if (wc < 0x800)