diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2008-04-01 12:19:20 -0400 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2008-04-01 12:19:20 -0400 |
commit | 9efddcf6e2facc7ed21e755785c3cec9f76f71b2 (patch) | |
tree | 5183d59a343bde1ac1ada477245436ea92e30b26 /sql | |
parent | 33529392d38f2653c7596a2d8714478c8d908f55 (diff) | |
download | mariadb-git-9efddcf6e2facc7ed21e755785c3cec9f76f71b2.tar.gz |
Bug#15776: 32-bit signed int used for length of blob
Based on contributed patch from Martin Friebe, CLA from 2007-02-24.
The parser lacked support for field sizes after signed long,
when it should extend to 2**32-1.
Now, we correct that limitation, and also make the error handling
consistent for casts.
---
Fix minor complaints of Marc Alff, for patch against B-g#15776.
---
Merge zippy.cornsilk.net:/home/cmiller/work/mysql/bug15776/my50-bug15776
into zippy.cornsilk.net:/home/cmiller/work/mysql/bug15776/my51-bug15776
---
Merge zippy.cornsilk.net:/home/cmiller/work/mysql/bug15776/my51-bug15776
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-build
---
testing
mysql-test/r/type_blob.result:
Verify that blobs may be created with the size that is already
documented.
Additionally, test the limits of several other types.
mysql-test/t/type_blob.test:
Verify that blobs may be created with the size that is already
documented.
Additionally, test the limits of several other types.
---
Drop table in case we start from a bad state.
sql/field.cc:
atoi() insufficient to gauge the length of some fields. Change
it to strtoul().
sql/item_create.cc:
atoi() insufficient to gauge the length of some fields. Change
it to strtoul().
If a casted length is too long, raise an error.
sql/share/errmsg.txt:
Change ER_TOO_BIG_FIELDLENGTH so that it can accept sizes larger
than 2**15 -- instead, 2**32.
---
Manual merge.
sql/sql_yacc.yy:
Make lengths take, in addition to NUM, LONG_NUM, ULONGLONG_NUM,
and DECIMAL_NUM.
---
yacc/bison is left-recursive, so FIXME statement is wrong.
---
Manual merge and reformatting.
sql/unireg.h:
Define new constant.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 16 | ||||
-rw-r--r-- | sql/item_create.cc | 54 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 60 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 56 | ||||
-rw-r--r-- | sql/unireg.h | 1 |
5 files changed, 124 insertions, 63 deletions
diff --git a/sql/field.cc b/sql/field.cc index 32bf5855d8b..c8645aa5a4f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9449,8 +9449,20 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, (fld_type_modifier & NOT_NULL_FLAG) && fld_type != MYSQL_TYPE_TIMESTAMP) flags|= NO_DEFAULT_VALUE_FLAG; - if (fld_length && !(length= (uint) atoi(fld_length))) - fld_length= 0; /* purecov: inspected */ + if (fld_length != 0) + { + errno= 0; + length= strtoul(fld_length, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH); + DBUG_RETURN(TRUE); + } + + if (length == 0) + fld_length= 0; /* purecov: inspected */ + } + sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1; switch (fld_type) { diff --git a/sql/item_create.cc b/sql/item_create.cc index 49cc33b95a7..427857c58ad 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5057,8 +5057,41 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, break; case ITEM_CAST_DECIMAL: { - len= c_len ? atoi(c_len) : 0; - dec= c_dec ? atoi(c_dec) : 0; + if (c_len == NULL) + { + len= 0; + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_len, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name, + DECIMAL_MAX_PRECISION); + return NULL; + } + len= decoded_size; + } + + if (c_dec == NULL) + { + dec= 0; + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_dec, NULL, 10); + if ((errno != 0) || (decoded_size > UINT_MAX)) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name, + DECIMAL_MAX_SCALE); + return NULL; + } + dec= decoded_size; + } my_decimal_trim(&len, &dec); if (len < dec) { @@ -5083,7 +5116,22 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, case ITEM_CAST_CHAR: { CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection); - len= c_len ? atoi(c_len) : -1; + if (c_len == NULL) + { + len= LL(-1); + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_len, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH); + return NULL; + } + len= decoded_size; + } res= new (thd->mem_root) Item_char_typecast(a, len, real_cs); break; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7990baa6bb7..dcc3220e425 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -1773,30 +1773,30 @@ ER_BLOB_USED_AS_KEY 42000 S1009 swe "En BLOB '%-.192s' kan inte vara nyckel med den anvnda tabelltypen" ukr "BLOB '%-.192s' Φ Ц æ" ER_TOO_BIG_FIELDLENGTH 42000 S1009 - cze "P-Bli velk dlka sloupce '%-.192s' (nejvce %d). Pouijte BLOB" - dan "For stor feltlngde for kolonne '%-.192s' (maks = %d). Brug BLOB i stedet" - nla "Te grote kolomlengte voor '%-.192s' (max = %d). Maak hiervoor gebruik van het type BLOB" - eng "Column length too big for column '%-.192s' (max = %d); use BLOB or TEXT instead" - jps "column '%-.192s' ,mۂ column ̑傫܂. (ő %d ܂). BLOB ɎgpĂ.", - est "Tulba '%-.192s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB vljatpi" - fre "Champ '%-.192s' trop long (max = %d). Utilisez un BLOB" - ger "Feldlnge fr Feld '%-.192s' zu gro (maximal %d). BLOB- oder TEXT-Spaltentyp verwenden!" - greek " '%-.192s' (max = %d). BLOB" - hun "A(z) '%-.192s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb." - ita "La colonna '%-.192s' e` troppo grande (max=%d). Utilizza un BLOB." - jpn "column '%-.192s' ,ݤ column 礭¿ޤ. ( %d ޤ). BLOB ˻ѤƤ." - kor "Į '%-.192s' Į ̰ ʹ ϴ (ִ = %d). ſ BLOB ϼ." - nor "For stor nkkellengde for kolonne '%-.192s' (maks = %d). Bruk BLOB istedenfor" - norwegian-ny "For stor nykkellengde for felt '%-.192s' (maks = %d). Bruk BLOB istadenfor" - pol "Zbyt dua dugo? kolumny '%-.192s' (maks. = %d). W zamian uyj typu BLOB" - por "Comprimento da coluna '%-.192s' grande demais (max = %d); use BLOB em seu lugar" - rum "Lungimea coloanei '%-.192s' este prea lunga (maximum = %d). Foloseste BLOB mai bine" - rus " '%-.192s' ( = %d). BLOB TEXT " - serbian "Previe podataka za kolonu '%-.192s' (maksimum je %d). Upotrebite BLOB polje" - slo "Prli vek dka pre pole '%-.192s' (maximum = %d). Pouite BLOB" - spa "Longitud de columna demasiado grande para la columna '%-.192s' (maximo = %d).Usar BLOB en su lugar" - swe "Fr stor kolumnlngd angiven fr '%-.192s' (max= %d). Anvnd en BLOB instllet" - ukr " '%-.192s' (max = %d). BLOB" + cze "P-Bli velk dlka sloupce '%-.192s' (nejvce %lu). Pouijte BLOB" + dan "For stor feltlngde for kolonne '%-.192s' (maks = %lu). Brug BLOB i stedet" + nla "Te grote kolomlengte voor '%-.192s' (max = %lu). Maak hiervoor gebruik van het type BLOB" + eng "Column length too big for column '%-.192s' (max = %lu); use BLOB or TEXT instead" + jps "column '%-.192s' ,mۂ column ̑傫܂. (ő %lu ܂). BLOB ɎgpĂ.", + est "Tulba '%-.192s' pikkus on liiga pikk (maksimaalne pikkus: %lu). Kasuta BLOB vljatpi" + fre "Champ '%-.192s' trop long (max = %lu). Utilisez un BLOB" + ger "Feldlnge fr Feld '%-.192s' zu gro (maximal %lu). BLOB- oder TEXT-Spaltentyp verwenden!" + greek " '%-.192s' (max = %lu). BLOB" + hun "A(z) '%-.192s' oszlop tul hosszu. (maximum = %lu). Hasznaljon BLOB tipust inkabb." + ita "La colonna '%-.192s' e` troppo grande (max=%lu). Utilizza un BLOB." + jpn "column '%-.192s' ,ݤ column 礭¿ޤ. ( %lu ޤ). BLOB ˻ѤƤ." + kor "Į '%-.192s' Į ̰ ʹ ϴ (ִ = %lu). ſ BLOB ϼ." + nor "For stor nkkellengde for kolonne '%-.192s' (maks = %lu). Bruk BLOB istedenfor" + norwegian-ny "For stor nykkellengde for felt '%-.192s' (maks = %lu). Bruk BLOB istadenfor" + pol "Zbyt dua dugo? kolumny '%-.192s' (maks. = %lu). W zamian uyj typu BLOB" + por "Comprimento da coluna '%-.192s' grande demais (max = %lu); use BLOB em seu lugar" + rum "Lungimea coloanei '%-.192s' este prea lunga (maximum = %lu). Foloseste BLOB mai bine" + rus " '%-.192s' ( = %lu). BLOB TEXT " + serbian "Previe podataka za kolonu '%-.192s' (maksimum je %lu). Upotrebite BLOB polje" + slo "Prli vek dka pre pole '%-.192s' (maximum = %lu). Pouite BLOB" + spa "Longitud de columna demasiado grande para la columna '%-.192s' (maximo = %lu).Usar BLOB en su lugar" + swe "Fr stor kolumnlngd angiven fr '%-.192s' (max= %lu). Anvnd en BLOB instllet" + ukr " '%-.192s' (max = %lu). BLOB" ER_WRONG_AUTO_KEY 42000 S1009 cze "M-Bete mt pouze jedno AUTO pole a to mus bt definovno jako kl" dan "Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal vre indekseret" @@ -5513,11 +5513,11 @@ ER_SP_NO_RECURSION eng "Recursive stored functions and triggers are not allowed." ger "Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt" ER_TOO_BIG_SCALE 42000 S1009 - eng "Too big scale %d specified for column '%-.192s'. Maximum is %d." - ger "Zu groer Skalierungsfaktor %d fr Feld '%-.192s' angegeben. Maximum ist %d" + eng "Too big scale %d specified for column '%-.192s'. Maximum is %lu" + ger "Zu groer Skalierungsfaktor %d fr Feld '%-.192s' angegeben. Maximum ist %lu" ER_TOO_BIG_PRECISION 42000 S1009 - eng "Too big precision %d specified for column '%-.192s'. Maximum is %d." - ger "Zu groe Genauigkeit %d fr Feld '%-.192s' angegeben. Maximum ist %d" + eng "Too big precision %d specified for column '%-.192s'. Maximum is %lu" + ger "Zu groe Genauigkeit %d fr Feld '%-.192s' angegeben. Maximum ist %lu" ER_M_BIGGER_THAN_D 42000 S1009 eng "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.192s')." ger "Fr FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%-.192s')" @@ -5554,8 +5554,8 @@ ER_WARN_CANT_DROP_DEFAULT_KEYCACHE eng "Cannot drop default keycache" ger "Der vorgabemige Schlssel-Cache kann nicht gelscht werden" ER_TOO_BIG_DISPLAYWIDTH 42000 S1009 - eng "Display width out of range for column '%-.192s' (max = %d)" - ger "Anzeigebreite auerhalb des zulssigen Bereichs fr Spalte '%-.192s' (Maximum: %d)" + eng "Display width out of range for column '%-.192s' (max = %lu)" + ger "Anzeigebreite auerhalb des zulssigen Bereichs fr Spalte '%-.192s' (Maximum: %lu)" ER_XAER_DUPID XAE08 eng "XAER_DUPID: The XID already exists" ger "XAER_DUPID: Die XID existiert bereits" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5e28bdb45e8..983356a47b1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1277,7 +1277,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); single_multi table_wild_list table_wild_one opt_wild union_clause union_list precision subselect_start opt_and charset - subselect_end select_var_list select_var_list_init help opt_len + subselect_end select_var_list select_var_list_init help + field_length opt_field_length opt_extended_describe prepare prepare_src execute deallocate statement sp_suid @@ -4628,7 +4629,7 @@ field_spec: ; type: - int_type opt_len field_options { $$=$1; } + int_type opt_field_length field_options { $$=$1; } | real_type opt_precision field_options { $$=$1; } | FLOAT_SYM float_options field_options { $$=MYSQL_TYPE_FLOAT; } | BIT_SYM @@ -4636,9 +4637,8 @@ type: Lex->length= (char*) "1"; $$=MYSQL_TYPE_BIT; } - | BIT_SYM '(' NUM ')' + | BIT_SYM field_length { - Lex->length= $3.str; $$=MYSQL_TYPE_BIT; } | BOOL_SYM @@ -4651,9 +4651,8 @@ type: Lex->length=(char*) "1"; $$=MYSQL_TYPE_TINY; } - | char '(' NUM ')' opt_binary + | char field_length opt_binary { - Lex->length=$3.str; $$=MYSQL_TYPE_STRING; } | char opt_binary @@ -4661,9 +4660,8 @@ type: Lex->length=(char*) "1"; $$=MYSQL_TYPE_STRING; } - | nchar '(' NUM ')' opt_bin_mod + | nchar field_length opt_bin_mod { - Lex->length=$3.str; $$=MYSQL_TYPE_STRING; Lex->charset=national_charset_info; } @@ -4673,9 +4671,8 @@ type: $$=MYSQL_TYPE_STRING; Lex->charset=national_charset_info; } - | BINARY '(' NUM ')' + | BINARY field_length { - Lex->length=$3.str; Lex->charset=&my_charset_bin; $$=MYSQL_TYPE_STRING; } @@ -4685,30 +4682,27 @@ type: Lex->charset=&my_charset_bin; $$=MYSQL_TYPE_STRING; } - | varchar '(' NUM ')' opt_binary + | varchar field_length opt_binary { - Lex->length=$3.str; $$= MYSQL_TYPE_VARCHAR; } - | nvarchar '(' NUM ')' opt_bin_mod + | nvarchar field_length opt_bin_mod { - Lex->length=$3.str; $$= MYSQL_TYPE_VARCHAR; Lex->charset=national_charset_info; } - | VARBINARY '(' NUM ')' + | VARBINARY field_length { - Lex->length=$3.str; Lex->charset=&my_charset_bin; $$= MYSQL_TYPE_VARCHAR; } - | YEAR_SYM opt_len field_options + | YEAR_SYM opt_field_length field_options { $$=MYSQL_TYPE_YEAR; } | DATE_SYM { $$=MYSQL_TYPE_DATE; } | TIME_SYM { $$=MYSQL_TYPE_TIME; } - | TIMESTAMP opt_len + | TIMESTAMP opt_field_length { if (YYTHD->variables.sql_mode & MODE_MAXDB) $$=MYSQL_TYPE_DATETIME; @@ -4728,7 +4722,7 @@ type: Lex->charset=&my_charset_bin; $$=MYSQL_TYPE_TINY_BLOB; } - | BLOB_SYM opt_len + | BLOB_SYM opt_field_length { Lex->charset=&my_charset_bin; $$=MYSQL_TYPE_BLOB; @@ -4764,7 +4758,7 @@ type: { $$=MYSQL_TYPE_MEDIUM_BLOB; } | TINYTEXT opt_binary { $$=MYSQL_TYPE_TINY_BLOB; } - | TEXT_SYM opt_len opt_binary + | TEXT_SYM opt_field_length opt_binary { $$=MYSQL_TYPE_BLOB; } | MEDIUMTEXT opt_binary { $$=MYSQL_TYPE_MEDIUM_BLOB; } @@ -4854,8 +4848,8 @@ real_type: float_options: /* empty */ { Lex->dec=Lex->length= (char*)0; } - | '(' NUM ')' - { Lex->length=$2.str; Lex->dec= (char*)0; } + | field_length + { Lex->dec= (char*)0; } | precision {} ; @@ -4885,9 +4879,15 @@ field_option: | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; } ; -opt_len: - /* empty */ { Lex->length=(char*) 0; /* use default length */ } - | '(' NUM ')' { Lex->length= $2.str; } +field_length: + '(' LONG_NUM ')' { Lex->length= $2.str; } + | '(' ULONGLONG_NUM ')' { Lex->length= $2.str; } + | '(' DECIMAL_NUM ')' { Lex->length= $2.str; } + | '(' NUM ')' { Lex->length= $2.str; }; + +opt_field_length: + /* empty */ { Lex->length=(char*) 0; /* use default length */ } + | field_length { } ; opt_precision: @@ -7450,11 +7450,11 @@ in_sum_expr: ; cast_type: - BINARY opt_len + BINARY opt_field_length { $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; } - | CHAR_SYM opt_len opt_binary + | CHAR_SYM opt_field_length opt_binary { $$=ITEM_CAST_CHAR; Lex->dec= 0; } - | NCHAR_SYM opt_len + | NCHAR_SYM opt_field_length { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; } | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; } diff --git a/sql/unireg.h b/sql/unireg.h index 18c3ab16f6a..c1c0e11e113 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -63,6 +63,7 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 #define MAX_FIELD_VARCHARLENGTH 65535 +#define MAX_FIELD_BLOBLENGTH UINT_MAX #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */ /* Max column width +1 */ |