summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2005-03-17 12:27:45 +0100
committerunknown <serg@serg.mylan>2005-03-17 12:27:45 +0100
commitb6e29d09b0c22037f7c1d54c55c76045a01b03ac (patch)
tree6647c711e18c396c34022d37fca3cc74234620f2
parent278e691ba885480cb1ab0879d1464ecbd8d3803f (diff)
downloadmariadb-git-b6e29d09b0c22037f7c1d54c55c76045a01b03ac.tar.gz
Field::quote_data():
don't call escape_string_for_mysql() unnecesary don't overwrite local buffer escape_string_for_mysql(): take a length of the destination buffer as an argument include/my_sys.h: prototype changed libmysql/libmysql.c: prototype changed mysys/charset.c: escape_string_for_mysql(): take a length of the destination buffer as an argument sql/field.cc: Field::quote_data(): don't call escape_string_for_mysql() unnecesary don't overwrite local buffer sql/item.cc: prototype changed sql/sql_prepare.cc: prototype changed
-rw-r--r--include/my_sys.h3
-rw-r--r--libmysql/libmysql.c4
-rw-r--r--mysys/charset.c75
-rw-r--r--sql/field.cc23
-rw-r--r--sql/item.cc2
-rw-r--r--sql/sql_prepare.cc2
6 files changed, 64 insertions, 45 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index afd2803b75d..c4385cd5fd2 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -845,7 +845,8 @@ extern char *get_charsets_dir(char *buf);
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
extern my_bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs);
-extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length);
extern void thd_increment_bytes_sent(ulong length);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 20a000f1e4d..7e5d9667be2 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1575,14 +1575,14 @@ mysql_hex_string(char *to, const char *from, ulong length)
ulong STDCALL
mysql_escape_string(char *to,const char *from,ulong length)
{
- return escape_string_for_mysql(default_charset_info, to, from, length);
+ return escape_string_for_mysql(default_charset_info, to, 0, from, length);
}
ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length)
{
- return escape_string_for_mysql(mysql->charset, to, from, length);
+ return escape_string_for_mysql(mysql->charset, to, 0, from, length);
}
diff --git a/mysys/charset.c b/mysys/charset.c
index 4b7ad3e59f4..a4a8205a3f9 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -547,10 +547,10 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_PRINT("enter",("name: '%s'", cs_name));
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
+
cs_number= get_charset_number(cs_name, cs_flags);
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
-
+
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
@@ -561,21 +561,34 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_RETURN(cs);
}
-
-ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+/*
+ NOTE
+ to keep old C API, to_length may be 0 to mean "big enough"
+ RETURN
+ the length of the escaped string or ~0 if it did not fit.
+*/
+ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
- const char *end;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow=0;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
- for (end= from + length; from != end; from++)
+ for (end= from + length; from < end; from++)
{
+ char escape=0;
#ifdef USE_MB
int l;
if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
{
+ if (to + l >= to_end)
+ {
+ overflow=1;
+ break;
+ }
while (l--)
*to++= *from++;
from--;
@@ -593,45 +606,53 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/
if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1)
- {
- *to++= '\\';
- *to++= *from;
- continue;
- }
+ escape= *from;
+ else
#endif
switch (*from) {
case 0: /* Must be escaped for 'mysql' */
- *to++= '\\';
- *to++= '0';
+ escape= '0';
break;
case '\n': /* Must be escaped for logs */
- *to++= '\\';
- *to++= 'n';
+ escape= 'n';
break;
case '\r':
- *to++= '\\';
- *to++= 'r';
+ escape= 'r';
break;
case '\\':
- *to++= '\\';
- *to++= '\\';
+ escape= '\\';
break;
case '\'':
- *to++= '\\';
- *to++= '\'';
+ escape= '\'';
break;
case '"': /* Better safe than sorry */
- *to++= '\\';
- *to++= '"';
+ escape= '"';
break;
case '\032': /* This gives problems on Win32 */
- *to++= '\\';
- *to++= 'Z';
+ escape= 'Z';
break;
- default:
+ }
+ if (escape)
+ {
+ if (to + 2 >= to_end)
+ {
+ overflow=1;
+ break;
+ }
+ *to++= '\\';
+ *to++= escape;
+ }
+ else
+ {
+ if (to + 1 >= to_end)
+ {
+ overflow=1;
+ break;
+ }
*to++= *from;
}
}
*to= 0;
- return (ulong) (to - to_start);
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
+
diff --git a/sql/field.cc b/sql/field.cc
index b6dd00d62a7..ae9b76e2dc4 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -752,25 +752,22 @@ bool Field::quote_data(String *unquoted_string)
{
char escaped_string[IO_SIZE];
char *unquoted_string_buffer= (char *)(unquoted_string->ptr());
- uint need_quotes;
DBUG_ENTER("Field::quote_data");
- // this is the same call that mysql_real_escape_string() calls
- escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
- unquoted_string->ptr(), unquoted_string->length());
-
- need_quotes= needs_quotes();
-
- if (need_quotes == 0)
+ if (!needs_quotes())
DBUG_RETURN(0);
+ // this is the same call that mysql_real_escape_string() calls
+ if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
+ sizeof(escaped_string), unquoted_string->ptr(),
+ unquoted_string->length()) == (ulong)~0)
+ DBUG_RETURN(1);
+
// reset string, then re-append with quotes and escaped values
unquoted_string->length(0);
- if (unquoted_string->append('\''))
- DBUG_RETURN(1);
- if (unquoted_string->append((char *)escaped_string))
- DBUG_RETURN(1);
- if (unquoted_string->append('\''))
+ if (unquoted_string->append('\'') ||
+ unquoted_string->append((char *)escaped_string) ||
+ unquoted_string->append('\''))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
diff --git a/sql/item.cc b/sql/item.cc
index e6be934e334..3489c54286c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2038,7 +2038,7 @@ const String *Item_param::query_val_str(String* str) const
buf= str->c_ptr_quick();
ptr= buf;
*ptr++= '\'';
- ptr+= escape_string_for_mysql(str_value.charset(), ptr,
+ ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
str_value.ptr(), str_value.length());
*ptr++= '\'';
str->length(ptr - buf);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 7862717bb18..1cbc52a2a5a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -865,7 +865,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
*ptr++= '\'';
ptr+=
escape_string_for_mysql(&my_charset_utf8_general_ci,
- ptr, entry->name.str, entry->name.length);
+ ptr, 0, entry->name.str, entry->name.length);
*ptr++= '\'';
str.length(ptr - buf);