Below is the list of changes that have just been committed into a local
5.1 repository of . When does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-03-09 17:37:39-05:00, Damien@damiendev. +1 -0
bug#26346 stack + buffer overrun in mysqldump
client/mysqldump.c@stripped, 2007-03-09 17:37:35-05:00, Damien@damiendev. +109 -76
fix in progress
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: Damien
# Host: damiendev.
# Root: C:/build/dev
--- 1.268/client/mysqldump.c 2007-02-23 06:23:36 -05:00
+++ 1.269/client/mysqldump.c 2007-03-09 17:37:35 -05:00
@@ -72,18 +72,20 @@
/* Size of buffer for dump's select query */
#define QUERY_LENGTH 1536
+#define CHECK_DYN(X) if(X) {ignore_errors=0; safe_exit(EX_MYSQLERR); /* fatal error, force exit */}
+
/* ignore table flags */
#define IGNORE_NONE 0x00 /* no ignore */
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
-static char *add_load_option(char *ptr, const char *object,
+static void add_load_option(DYNAMIC_STRING* str, const char *object,
const char *statement);
static ulong find_set(TYPELIB *lib, const char *x, uint length,
char **err_pos, uint *err_len);
static char *alloc_query_str(ulong size);
-static char *field_escape(char *to,const char *from,uint length);
+static void field_escape(DYNAMIC_STRING* in,const char *from,uint length);
static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
quick= 1, extended_insert= 1,
lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
@@ -2256,23 +2258,36 @@
DBUG_VOID_RETURN;
}
-static char *add_load_option(char *ptr,const char *object,
+static void add_load_option(DYNAMIC_STRING *str, const char *object,
const char *statement)
{
if (object)
{
- /* Don't escape hex constants */
+ CHECK_DYN(dynstr_append(str, " "));
+ CHECK_DYN(dynstr_append(str, statement));
+ CHECK_DYN(dynstr_append(str, " "));
+
+
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
- ptr= strxmov(ptr," ",statement," ",object,NullS);
+ {
+ /* Don't escape hex constants */
+ CHECK_DYN(dynstr_append(str, object));
+ }
else
{
/* char constant; escape */
- ptr= strxmov(ptr," ",statement," '",NullS);
- ptr= field_escape(ptr,object,(uint) strlen(object));
- *ptr++= '\'';
+ /* It's looks like we could replace this with
+ dynstr_append_os_quoted and accomplish the same
+ thing (escaping quotes for nested strings). However,
+ the field_escape version will add a trailing backslash
+ if one is missing. So its best to continue to use this
+ version for now.
+ */
+ CHECK_DYN(dynstr_append(str, "'"));
+ field_escape(str, object, (uint)strlen(object));
+ CHECK_DYN(dynstr_append(str, "'"));
}
}
- return ptr;
} /* add_load_option */
@@ -2283,27 +2298,36 @@
syntax errors from the SQL parser.
*/
-static char *field_escape(char *to,const char *from,uint length)
+static void field_escape(DYNAMIC_STRING* in, const char *from, uint length)
{
+
const char *end;
uint end_backslashes=0;
+ /* used with dynstr_appendr to append one char strings */
+ char str_buf[2] = {0,0};
+
for (end= from+length; from != end; from++)
{
- *to++= *from;
+ str_buf[0] = *from; /* set the char and append the string */
+ CHECK_DYN(dynstr_append(in, str_buf));
+
if (*from == '\\')
end_backslashes^=1; /* find odd number of backslashes */
else
{
- if (*from == '\'' && !end_backslashes)
- *to++= *from; /* We want a duplicate of "'" for MySQL */
+ if (*from == '\'' && !end_backslashes) {
+ /* We want a duplicate of "'" for MySQL */
+ CHECK_DYN(dynstr_append(in, "\'"));
+ }
end_backslashes=0;
}
}
/* Add missing backslashes if user has specified odd number of backs.*/
- if (end_backslashes)
- *to++= '\\';
- return to;
+ if (end_backslashes) {
+ CHECK_DYN(dynstr_append(in, "\\"));
+ }
+
} /* field_escape */
@@ -2338,10 +2362,10 @@
static void dump_table(char *table, char *db)
{
char ignore_flag;
- char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
+ char buf[200], table_buff[NAME_LEN+3];
+ DYNAMIC_STRING query_string;
char table_type[NAME_LEN];
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
- char *query= query_buf;
int error= 0;
ulong rownr, row_break, total_length, init_length;
uint num_fields;
@@ -2395,44 +2419,58 @@
opt_quoted_table= quote_name(table, table_buff2, 0);
verbose_msg("-- Sending SELECT query...\n");
+
+ CHECK_DYN(init_dynamic_string(&query_string, "", 1024, 1024));
+
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+
+ if (FN_REFLEN < strlen(path) + 1)
+ {
+ fprintf(stderr, "Error: Input arguments too long\n");
+ fflush(stderr);
+ ignore_errors= 0; /* Fatal error */
+ safe_exit(EX_USAGE);
+ DBUG_VOID_RETURN;
+ }
+
convert_dirname(tmp_path,path,NullS);
my_load_path(tmp_path, tmp_path, NULL);
fn_format(filename, table, tmp_path, ".txt", 4);
my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
filename wasn't deleted */
to_unix_path(filename);
- my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
- filename);
- end= strend(query);
+
+ CHECK_DYN(dynstr_append(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '"));
+ CHECK_DYN(dynstr_append(&query_string, filename));
+ CHECK_DYN(dynstr_append(&query_string, "'"));
if (fields_terminated || enclosed || opt_enclosed || escaped)
- end= strmov(end, " FIELDS");
- end= add_load_option(end, fields_terminated, " TERMINATED BY");
- end= add_load_option(end, enclosed, " ENCLOSED BY");
- end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
- end= add_load_option(end, escaped, " ESCAPED BY");
- end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
- *end= '\0';
-
- my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
- end= strmov(end,buff);
- if (where || order_by)
- {
- query= alloc_query_str((ulong) ((end - query) + 1 +
- (where ? strlen(where) + 7 : 0) +
- (order_by ? strlen(order_by) + 10 : 0)));
- end= strmov(query, query_buf);
-
- if (where)
- end= strxmov(end, " WHERE ", where, NullS);
- if (order_by)
- end= strxmov(end, " ORDER BY ", order_by, NullS);
+ CHECK_DYN(dynstr_append(&query_string, " FIELDS"));
+
+ add_load_option(&query_string, fields_terminated, " TERMINATED BY");
+ add_load_option(&query_string, enclosed, " ENCLOSED BY");
+ add_load_option(&query_string, opt_enclosed, " OPTIONALLY ENCLOSED BY");
+ add_load_option(&query_string, escaped, " ESCAPED BY");
+ add_load_option(&query_string, lines_terminated, " LINES TERMINATED BY");
+
+ CHECK_DYN(dynstr_append(&query_string, " FROM "));
+ CHECK_DYN(dynstr_append(&query_string, result_table));
+
+ if (where)
+ {
+ CHECK_DYN(dynstr_append(&query_string, " WHERE "));
+ CHECK_DYN(dynstr_append(&query_string, where));
}
- if (mysql_real_query(mysql, query, (uint) (end - query)))
+
+ if (order_by)
+ {
+ CHECK_DYN(dynstr_append(&query_string, " ORDER BY "));
+ CHECK_DYN(dynstr_append(&query_string, order_by));
+ }
+
+ if (mysql_real_query(mysql, query_string.str, query_string.length))
{
DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
DBUG_VOID_RETURN;
@@ -2446,41 +2484,38 @@
result_table);
check_io(md_result_file);
}
- my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
- result_table);
- if (where || order_by)
- {
- query= alloc_query_str((ulong) (strlen(query) + 1 +
- (where ? strlen(where) + 7 : 0) +
- (order_by ? strlen(order_by) + 10 : 0)));
- end= strmov(query, query_buf);
+
+ CHECK_DYN(dynstr_append(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "));
+ CHECK_DYN(dynstr_append(&query_string, result_table));
- if (where)
+ if (where)
+ {
+ if (!opt_xml && opt_comments)
{
- if (!opt_xml && opt_comments)
- {
- fprintf(md_result_file, "-- WHERE: %s\n", where);
- check_io(md_result_file);
- }
- end= strxmov(end, " WHERE ", where, NullS);
+ fprintf(md_result_file, "-- WHERE: %s\n", where);
+ check_io(md_result_file);
}
- if (order_by)
+
+ CHECK_DYN(dynstr_append(&query_string, " WHERE "));
+ CHECK_DYN(dynstr_append(&query_string, where));
+ }
+ if (order_by)
+ {
+ if (!opt_xml && opt_comments)
{
- if (!opt_xml && opt_comments)
- {
- fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
- check_io(md_result_file);
- }
- end= strxmov(end, " ORDER BY ", order_by, NullS);
+ fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
+ check_io(md_result_file);
}
+ CHECK_DYN(dynstr_append(&query_string, " ORDER BY "));
+ CHECK_DYN(dynstr_append(&query_string, order_by));
}
+
if (!opt_xml && !opt_compact)
{
fputs("\n", md_result_file);
check_io(md_result_file);
}
- if (mysql_query_with_error_report(mysql, 0, query))
+ if (mysql_query_with_error_report(mysql, 0, query_string.str))
{
DB_error(mysql, "when retrieving data from server");
goto err;
@@ -2555,10 +2590,10 @@
if (!(field= mysql_fetch_field(res)))
{
- my_snprintf(query, QUERY_LENGTH,
+ my_snprintf(buf, sizeof(buf),
"%s: Not enough fields from table %s! Aborting.\n",
my_progname, result_table);
- fputs(query,stderr);
+ fputs(buf,stderr);
error= EX_CONSCHECK;
goto err;
}
@@ -2773,14 +2808,14 @@
check_io(md_result_file);
if (mysql_errno(mysql))
{
- my_snprintf(query, QUERY_LENGTH,
+ my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
my_progname,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
rownr);
- fputs(query,stderr);
+ fputs(buf,stderr);
error= EX_CONSCHECK;
goto err;
}
@@ -2803,14 +2838,12 @@
check_io(md_result_file);
}
mysql_free_result(res);
- if (query != query_buf)
- my_free(query, MYF(MY_ALLOW_ZERO_PTR));
+ dynstr_free(&query_string);
}
DBUG_VOID_RETURN;
err:
- if (query != query_buf)
- my_free(query, MYF(MY_ALLOW_ZERO_PTR));
+ dynstr_free(&query_string);
safe_exit(error);
DBUG_VOID_RETURN;
} /* dump_table */
| Thread |
|---|
| • bk commit into 5.1 tree (Damien:1.2466) BUG#26346 | damien | 9 Mar |