List:Commits« Previous MessageNext Message »
From:damien Date:March 16 2007 1:35am
Subject:bk commit into 5.0 tree (Damien:1.2400) BUG#26346
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 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-15 21:35:27-04:00, Damien@damiendev. +1 -0
  Bug#26346 stack + buffer overrun in mysqldump

  client/mysqldump.c@stripped, 2007-03-15 21:34:52-04:00, dkatz@damiendev. +293 -228
    Bug#26346 stack + buffer overrun in mysqldump
    
    These are changes to fix the buffer overruns, and refactor some of the less maintainable code.
    

# 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/dev50

--- 1.257/client/mysqldump.c	2007-02-22 09:59:54 -05:00
+++ 1.258/client/mysqldump.c	2007-03-15 21:34:52 -04:00
@@ -76,13 +76,13 @@
 #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,
-                             const char *statement);
+static void add_load_option(DYNAMIC_STRING *str, const char *option,
+                             const char *option_value);
 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);
 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,
@@ -121,6 +121,19 @@
 static char *shared_memory_base_name=0;
 #endif
 static uint opt_protocol= 0;
+
+/*
+Dynamic_string wrapper functions. In this file use these
+wrappers, they will terminate the process if there is
+an allocation failure.
+*/
+static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
+			    uint init_alloc, uint alloc_increment);
+static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src);
+static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str);
+static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
+			  uint length);
+static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size);
 /*
   Constant for detection of default value of default_charset.
   If default_charset is equal to mysql_universal_client_charset, then
@@ -419,7 +432,9 @@
 
 static const char *load_default_groups[]= { "mysqldump","client",0 };
 
-static void safe_exit(int error);
+static void maybe_exit(int error);
+static void die(int error, const char* reason, ...);
+static void maybe_die(int error, const char* reason, ...);
 static void write_header(FILE *sql_file, char *db_name);
 static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
                         const char *prefix,const char *name,
@@ -474,11 +489,7 @@
 void check_io(FILE *file)
 {
   if (ferror(file))
-  {
-    fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno);
-    ignore_errors= 0; /* We can't ignore this error */
-    safe_exit(EX_EOF);
-  }
+    die(EX_EOF, "Got errno %d on write", errno);
 }
 
 static void print_version(void)
@@ -864,12 +875,47 @@
 static void DB_error(MYSQL *mysql_arg, const char *when)
 {
   DBUG_ENTER("DB_error");
-  fprintf(stderr, "%s: Got error: %d: %s %s\n", my_progname,
+  maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
           mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
-  fflush(stderr);
-  safe_exit(EX_MYSQLERR);
   DBUG_VOID_RETURN;
-} /* DB_error */
+}
+
+/*
+** die -- fatal error encountered. Dump the error message and terminate the program.
+**
+*/
+static void die(int error_num, const char* fmt_reason, ...)
+{
+  char buffer[200];
+  va_list args;
+  va_start(args,fmt_reason);
+  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
+  va_end(args);
+
+  fprintf(stderr, "%s: %s", my_progname, buffer);
+  fflush(stderr);
+
+  ignore_errors= 0; /* force the exit */
+  maybe_exit(error_num);
+}
+
+/*
+** maybe_die -- Error encountered. Dump the error message and terminate the program.
+** unless the ignore_errors option was used.
+*/
+static void maybe_die(int error_num, const char* fmt_reason, ...)
+{
+  char buffer[1000];
+  va_list args;
+  va_start(args,fmt_reason);
+  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
+  va_end(args);
+
+  fprintf(stderr, "%s: %s\n", my_progname, buffer);
+  fflush(stderr);
+
+  maybe_exit(error_num);
+}
 
 
 /*
@@ -894,10 +940,8 @@
   if (mysql_query(mysql_con, query) ||
       (res && !((*res)= mysql_store_result(mysql_con))))
   {
-    fprintf(stderr, "%s: Couldn't execute '%s': %s (%d)\n",
-            my_progname, query,
-            mysql_error(mysql_con), mysql_errno(mysql_con));
-    safe_exit(EX_MYSQLERR);
+    maybe_die(EX_MYSQLERR, "Couldn't execute '%s': %s (%d)",
+            query, mysql_error(mysql_con), mysql_errno(mysql_con));
     return 1;
   }
   return 0;
@@ -942,7 +986,7 @@
 }
 
 
-static void safe_exit(int error)
+static void maybe_exit(int error)
 {
   if (!first_error)
     first_error= error;
@@ -1002,10 +1046,7 @@
   my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
               compatible_mode_normal_str);
   if (mysql_query_with_error_report(mysql, 0, buff))
-  {
-    safe_exit(EX_MYSQLERR);
     DBUG_RETURN(1);
-  }
   /*
     set time_zone to UTC to allow dumping date types between servers with
     different time zone settings
@@ -1014,10 +1055,7 @@
   {
     my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
     if (mysql_query_with_error_report(mysql, 0, buff))
-    {
-      safe_exit(EX_MYSQLERR);
       DBUG_RETURN(1);
-    }
   }
   DBUG_RETURN(0);
 } /* connect_to_db */
@@ -1038,10 +1076,8 @@
   char *tmp;
   DBUG_ENTER("unescape");
   if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
-  {
-    ignore_errors=0;                            /* Fatal error */
-    safe_exit(EX_MYSQLERR);                     /* Force exit */
-  }
+    die(EX_MYSQLERR, "Couldn't allocate memory");
+
   mysql_real_escape_string(&mysql_connection, tmp, pos, length);
   fputc('\'', file);
   fputs(tmp, file);
@@ -1350,7 +1386,7 @@
 
 /*
   dump_routines_for_db
-  -- retrievs list of routines for a given db, and prints out
+  -- retrieves list of routines for a given db, and prints out
   the CREATE PROCEDURE definition into the output (the dump).
 
   This function has logic to print the appropriate syntax depending on whether
@@ -1545,11 +1581,10 @@
     if (!insert_pat_inited)
     {
       insert_pat_inited= 1;
-      if (init_dynamic_string(&insert_pat, "", 1024, 1024))
-        safe_exit(EX_MYSQLERR);
+      init_dynamic_string_checked(&insert_pat, "", 1024, 1024);
     }
     else
-      dynstr_set(&insert_pat, "");
+      dynstr_set_checked(&insert_pat, "");
   }
 
   insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
@@ -1581,18 +1616,13 @@
 
       my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
       if (mysql_query_with_error_report(mysql, 0, buff))
-      {
-        safe_exit(EX_MYSQLERR);
         DBUG_RETURN(0);
-      }
 
       if (path)
       {
         if (!(sql_file= open_sql_file_for_table(table)))
-        {
-          safe_exit(EX_MYSQLERR);
           DBUG_RETURN(0);
-        }
+
         write_header(sql_file, db);
       }
       if (!opt_xml && opt_comments)
@@ -1656,7 +1686,6 @@
 
           my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
 
-          safe_exit(EX_MYSQLERR);
           DBUG_RETURN(0);
         }
         else
@@ -1719,7 +1748,6 @@
     {
       if (path)
         my_fclose(sql_file, MYF(MY_WME));
-      safe_exit(EX_MYSQLERR);
       DBUG_RETURN(0);
     }
 
@@ -1731,19 +1759,19 @@
     */
     if (write_data)
     {
-      dynstr_append_mem(&insert_pat, "INSERT ", 7);
-      dynstr_append(&insert_pat, insert_option);
-      dynstr_append_mem(&insert_pat, "INTO ", 5);
-      dynstr_append(&insert_pat, opt_quoted_table);
+      dynstr_append_checked(&insert_pat, "INSERT ");
+      dynstr_append_checked(&insert_pat, insert_option);
+      dynstr_append_checked(&insert_pat, "INTO ");
+      dynstr_append_checked(&insert_pat, opt_quoted_table);
       if (complete_insert)
       {
-        dynstr_append_mem(&insert_pat, " (", 2);
+        dynstr_append_checked(&insert_pat, " (");
       }
       else
       {
-        dynstr_append_mem(&insert_pat, " VALUES ", 8);
+        dynstr_append_checked(&insert_pat, " VALUES ");
         if (!extended_insert)
-          dynstr_append_mem(&insert_pat, "(", 1);
+          dynstr_append_checked(&insert_pat, "(");
       }
     }
 
@@ -1753,10 +1781,10 @@
       {
         if (init)
         {
-          dynstr_append_mem(&insert_pat, ", ", 2);
+          dynstr_append_checked(&insert_pat, ", ");
         }
         init=1;
-        dynstr_append(&insert_pat,
+        dynstr_append_checked(&insert_pat,
                       quote_name(row[SHOW_FIELDNAME], name_buff, 0));
       }
     }
@@ -1771,10 +1799,7 @@
     my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
                 result_table);
     if (mysql_query_with_error_report(mysql, &result, query_buff))
-    {
-      safe_exit(EX_MYSQLERR);
       DBUG_RETURN(0);
-    }
 
     /* Make an sql-file, if path was given iow. option -T was given */
     if (!opt_no_create_info)
@@ -1782,10 +1807,7 @@
       if (path)
       {
         if (!(sql_file= open_sql_file_for_table(table)))
-        {
-          safe_exit(EX_MYSQLERR);
           DBUG_RETURN(0);
-        }
         write_header(sql_file, db);
       }
       if (!opt_xml && opt_comments)
@@ -1803,17 +1825,17 @@
 
     if (write_data)
     {
-      dynstr_append_mem(&insert_pat, "INSERT ", 7);
-      dynstr_append(&insert_pat, insert_option);
-      dynstr_append_mem(&insert_pat, "INTO ", 5);
-      dynstr_append(&insert_pat, result_table);
+      dynstr_append_checked(&insert_pat, "INSERT ");
+      dynstr_append_checked(&insert_pat, insert_option);
+      dynstr_append_checked(&insert_pat, "INTO ");
+      dynstr_append_checked(&insert_pat, result_table);
       if (opt_complete_insert)
-        dynstr_append_mem(&insert_pat, " (", 2);
+        dynstr_append_checked(&insert_pat, " (");
       else
       {
-        dynstr_append_mem(&insert_pat, " VALUES ", 8);
+        dynstr_append_checked(&insert_pat, " VALUES ");
         if (!extended_insert)
-          dynstr_append_mem(&insert_pat, "(", 1);
+          dynstr_append_checked(&insert_pat, "(");
       }
     }
 
@@ -1828,11 +1850,11 @@
           check_io(sql_file);
         }
         if (complete_insert)
-          dynstr_append_mem(&insert_pat, ", ", 2);
+          dynstr_append_checked(&insert_pat, ", ");
       }
       init=1;
       if (opt_complete_insert)
-        dynstr_append(&insert_pat,
+        dynstr_append_checked(&insert_pat,
                       quote_name(row[SHOW_FIELDNAME], name_buff, 0));
       if (!opt_no_create_info)
       {
@@ -1882,7 +1904,6 @@
                 my_progname, result_table, mysql_error(mysql));
         if (path)
           my_fclose(sql_file, MYF(MY_WME));
-        safe_exit(EX_MYSQLERR);
         DBUG_RETURN(0);
       }
 
@@ -1992,9 +2013,9 @@
   }
   if (opt_complete_insert)
   {
-    dynstr_append_mem(&insert_pat, ") VALUES ", 9);
+    dynstr_append_checked(&insert_pat, ") VALUES ");
     if (!extended_insert)
-      dynstr_append_mem(&insert_pat, "(", 1);
+      dynstr_append_checked(&insert_pat, "(");
   }
   if (sql_file != md_result_file)
   {
@@ -2041,7 +2062,6 @@
   {
     if (path)
       my_fclose(sql_file, MYF(MY_WME));
-    safe_exit(EX_MYSQLERR);
     DBUG_VOID_RETURN;
   }
   if (mysql_num_rows(result))
@@ -2100,24 +2120,26 @@
   DBUG_VOID_RETURN;
 }
 
-static char *add_load_option(char *ptr,const char *object,
-                             const char *statement)
+static void add_load_option(DYNAMIC_STRING *str, const char *option,
+                             const char *option_value)
 {
-  if (object)
+  if (!option_value)
+    /* Null value means we don't add this option. */
+    return;
+
+  dynstr_append_checked(str, option);
+  
+  if (strstr(option_value, "0x") == option_value)
   {
-    /* Don't escape hex constants */
-    if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
-      ptr= strxmov(ptr," ",statement," ",object,NullS);
-    else
-    {
-      /* char constant; escape */
-      ptr= strxmov(ptr," ",statement," '",NullS);
-      ptr= field_escape(ptr,object,(uint) strlen(object));
-      *ptr++= '\'';
-    }
+    /* It's a hex constant, don't escape */
+    dynstr_append_checked(str, option_value);
   }
-  return ptr;
-} /* add_load_option */
+  else
+  {
+    /* char constant; escape */
+    field_escape(str, option_value);
+  }
+}
 
 
 /*
@@ -2127,28 +2149,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)
 {
-  const char *end;
-  uint end_backslashes=0;
+  uint end_backslashes=0; 
+
+  dynstr_append_checked(in, "'");
 
-  for (end= from+length; from != end; from++)
+  while (*from)
   {
-    *to++= *from;
+    dynstr_append_mem_checked(in, from, 1);
+
     if (*from == '\\')
       end_backslashes^=1;    /* find odd number of backslashes */
     else
     {
       if (*from == '\'' && !end_backslashes)
-        *to++= *from;      /* We want a duplicate of "'" for MySQL */
+      {
+        /* We want a duplicate of "'" for MySQL */
+        dynstr_append_checked(in, "\'");
+      }
       end_backslashes=0;
     }
+    from++;
   }
   /* Add missing backslashes if user has specified odd number of backs.*/
   if (end_backslashes)
-    *to++= '\\';
-  return to;
-} /* field_escape */
+    dynstr_append_checked(in, "\\");
+  
+  dynstr_append_checked(in, "'");
+}
+
 
 
 static char *alloc_query_str(ulong size)
@@ -2156,10 +2186,8 @@
   char *query;
 
   if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
-  {
-    ignore_errors= 0;                           /* Fatal error */
-    safe_exit(EX_MYSQLERR);                     /* Force exit */
-  }
+    die(EX_MYSQLERR, "Couldn't allocate a query string.");
+
   return query;
 }
 
@@ -2179,13 +2207,14 @@
     void
 */
 
+
 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;
@@ -2239,44 +2268,69 @@
   opt_quoted_table= quote_name(table, table_buff2, 0);
 
   verbose_msg("-- Sending SELECT query...\n");
+
+  init_dynamic_string_checked(&query_string, "", 1024, 1024);
+
   if (path)
   {
     char filename[FN_REFLEN], tmp_path[FN_REFLEN];
-    convert_dirname(tmp_path,path,NullS);
+
+    if (strlen(path) >= FN_REFLEN)
+    {
+      /*
+        This check is made because the some the file functions below
+        have FN_REFLEN sized stack allocated buffers and will cause
+        a crash even if the input destination buffer is large enough
+        to hold the output.
+      */
+      die(EX_USAGE, "Input filename or options too long: %s", path);
+    }
+
+    /*
+      Convert the path to native os format
+      and resolve to the full filepath.
+    */
+    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 */
+    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
+
+    /* Must delete the file that 'INTO OUTFILE' will write to */
+    my_delete(filename, MYF(0));
+
+    /* convert to a unix path name to stick into the query */
     to_unix_path(filename);
-    my_snprintf(query, QUERY_LENGTH,
-                "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
-                filename);
-    end= strend(query);
+
+    /* now build the query string */
+
+    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '");
+    dynstr_append_checked(&query_string, filename);
+    dynstr_append_checked(&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);
+      dynstr_append_checked(&query_string, " FIELDS");
+    
+    add_load_option(&query_string, " TERMINATED BY ", fields_terminated);
+    add_load_option(&query_string, " ENCLOSED BY ", enclosed);
+    add_load_option(&query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
+    add_load_option(&query_string, " ESCAPED BY ", escaped);
+    add_load_option(&query_string, " LINES TERMINATED BY ", lines_terminated);
+
+    dynstr_append_checked(&query_string, " FROM ");
+    dynstr_append_checked(&query_string, result_table);
+
+    if (where)
+    {
+      dynstr_append_checked(&query_string, " WHERE ");
+      dynstr_append_checked(&query_string, where);
+    }
+
+    if (order_by)
+    {
+      dynstr_append_checked(&query_string, " ORDER BY ");
+      dynstr_append_checked(&query_string, order_by);
     }
-    if (mysql_real_query(mysql, query, (uint) (end - query)))
+
+    if (mysql_real_query(mysql, query_string.str, query_string.length))
     {
       DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
       DBUG_VOID_RETURN;
@@ -2290,41 +2344,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);
+    
+    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
+    dynstr_append_checked(&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)
+      
+      dynstr_append_checked(&query_string, " WHERE ");
+      dynstr_append_checked(&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);
       }
+      dynstr_append_checked(&query_string, " ORDER BY ");
+      dynstr_append_checked(&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;
@@ -2398,14 +2449,9 @@
         ulong length= lengths[i];
 
         if (!(field= mysql_fetch_field(res)))
-        {
-          my_snprintf(query, QUERY_LENGTH,
-                      "%s: Not enough fields from table %s! Aborting.\n",
-                      my_progname, result_table);
-          fputs(query,stderr);
-          error= EX_CONSCHECK;
-          goto err;
-        }
+          die(EX_CONSCHECK,
+                      "Not enough fields from table %s! Aborting.\n",
+                      result_table);
 
         /*
            63 is my_charset_bin. If charsetnr is not 63,
@@ -2424,9 +2470,9 @@
         if (extended_insert && !opt_xml)
         {
           if (i == 0)
-            dynstr_set(&extended_row,"(");
+            dynstr_set_checked(&extended_row,"(");
           else
-            dynstr_append(&extended_row,",");
+            dynstr_append_checked(&extended_row,",");
 
           if (row[i])
           {
@@ -2441,15 +2487,10 @@
                   - In non-HEX mode we need up to 2 bytes per character,
                   plus 2 bytes for leading and trailing '\'' characters.
                 */
-                if (dynstr_realloc(&extended_row,length * 2+2))
-                {
-                  fputs("Aborting dump (out of memory)",stderr);
-                  error= EX_EOM;
-                  goto err;
-                }
+                dynstr_realloc_checked(&extended_row,length * 2+2);
                 if (opt_hex_blob && is_blob)
                 {
-                  dynstr_append(&extended_row, "0x");
+                  dynstr_append_checked(&extended_row, "0x");
                   extended_row.length+= mysql_hex_string(extended_row.str +
                                                          extended_row.length,
                                                          row[i], length);
@@ -2457,13 +2498,13 @@
                 }
                 else
                 {
-                  dynstr_append(&extended_row,"'");
+                  dynstr_append_checked(&extended_row,"'");
                   extended_row.length +=
                   mysql_real_escape_string(&mysql_connection,
                                            &extended_row.str[extended_row.length],
                                            row[i],length);
                   extended_row.str[extended_row.length]='\0';
-                  dynstr_append(&extended_row,"'");
+                  dynstr_append_checked(&extended_row,"'");
                 }
               }
               else
@@ -2472,30 +2513,26 @@
                 char *ptr= row[i];
                 if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
                     my_isalpha(charset_info, ptr[1])))
-                  dynstr_append(&extended_row, "NULL");
+                  dynstr_append_checked(&extended_row, "NULL");
                 else
                 {
                   if (field->type == FIELD_TYPE_DECIMAL)
                   {
                     /* add " signs around */
-                    dynstr_append(&extended_row, "'");
-                    dynstr_append(&extended_row, ptr);
-                    dynstr_append(&extended_row, "'");
+                    dynstr_append_checked(&extended_row, "'");
+                    dynstr_append_checked(&extended_row, ptr);
+                    dynstr_append_checked(&extended_row, "'");
                   }
                   else
-                    dynstr_append(&extended_row, ptr);
+                    dynstr_append_checked(&extended_row, ptr);
                 }
               }
             }
             else
-              dynstr_append(&extended_row,"''");
-          }
-          else if (dynstr_append(&extended_row,"NULL"))
-          {
-            fputs("Aborting dump (out of memory)",stderr);
-            error= EX_EOM;
-            goto err;
+              dynstr_append_checked(&extended_row,"''");
           }
+          else
+            dynstr_append_checked(&extended_row,"NULL");
         }
         else
         {
@@ -2512,16 +2549,16 @@
               {
                 if (opt_hex_blob && is_blob && length)
                 {
-                    /* Define xsi:type="xs:hexBinary" for hex encoded data */
-                    print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
-                            field->name, "xsi:type=", "xs:hexBinary", NullS);
-                    print_blob_as_hex(md_result_file, row[i], length);
+                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
+                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
+                                field->name, "xsi:type=", "xs:hexBinary", NullS);
+                  print_blob_as_hex(md_result_file, row[i], length);
                 }
                 else
                 {
-                    print_xml_tag(md_result_file, "\t\t", "", "field", "name=", 
-                            field->name, NullS);
-                    print_quoted_xml(md_result_file, row[i], length);
+                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=", 
+                                field->name, NullS);
+                  print_quoted_xml(md_result_file, row[i], length);
                 }
                 fputs("</field>\n", md_result_file);
               }
@@ -2581,7 +2618,7 @@
       if (extended_insert)
       {
         ulong row_length;
-        dynstr_append(&extended_row,")");
+        dynstr_append_checked(&extended_row,")");
         row_length= 2 + extended_row.length;
         if (total_length + row_length < opt_net_buffer_length)
         {
@@ -2617,14 +2654,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;
     }
@@ -2647,15 +2684,13 @@
       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));
-  safe_exit(error);
+  dynstr_free(&query_string);
+  maybe_exit(error);
   DBUG_VOID_RETURN;
 } /* dump_table */
 
@@ -2842,8 +2877,8 @@
       check_io(md_result_file);
     }
   }
-  if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
-    exit(EX_EOM);
+  if (extended_insert)
+    init_dynamic_string_checked(&extended_row, "", 1024, 1024);
   return 0;
 } /* init_dumping */
 
@@ -2876,11 +2911,11 @@
   if (lock_tables)
   {
     DYNAMIC_STRING query;
-    init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
+    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
     for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
     {
-      dynstr_append(&query, quote_name(table, table_buff, 1));
-      dynstr_append(&query, " READ /*!32311 LOCAL */,");
+      dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+      dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
     }
     if (numrows && mysql_real_query(mysql, query.str, query.length-1))
       DB_error(mysql, "when using LOCK TABLES");
@@ -2953,11 +2988,11 @@
   if (lock_tables)
   {
     DYNAMIC_STRING query;
-    init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
+    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
     for (numrows= 0 ; (table= getTableName(1)); numrows++)
     {
-      dynstr_append(&query, quote_name(table, table_buff, 1));
-      dynstr_append(&query, " READ /*!32311 LOCAL */,");
+      dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+      dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
     }
     if (numrows && mysql_real_query(mysql, query.str, query.length-1))
       DB_error(mysql, "when using LOCK TABLES");
@@ -3009,9 +3044,7 @@
               quote_for_like(old_table_name, show_name_buff));
 
   if (mysql_query_with_error_report(mysql, 0, query))
-  {
-    safe_exit(EX_MYSQLERR);
-  }
+    return NullS;
 
   if ((table_res= mysql_store_result(mysql)))
   {
@@ -3049,7 +3082,7 @@
   if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
      exit(EX_EOM);
 
-  init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
+  init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024);
   for (; tables > 0 ; tables-- , table_names++)
   {
     /* the table name passed on commandline may be wrong case */
@@ -3058,16 +3091,14 @@
       /* Add found table name to lock_tables_query */
       if (lock_tables)
       {
-        dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1));
-        dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
+        dynstr_append_checked(&lock_tables_query, quote_name(*pos, table_buff, 1));
+        dynstr_append_checked(&lock_tables_query, " READ /*!32311 LOCAL */,");
       }
       pos++;
     }
     else
     {
-       my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0),
-                       *table_names);
-       safe_exit(EX_ILLEGAL_TABLE);
+       maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
        /* We shall countinue here, if --force was given */
     }
   }
@@ -3482,12 +3513,12 @@
   const char *start= strstr(ds_str->str, search_str);
   if (!start)
     return 1;
-  init_dynamic_string(&ds_tmp, "",
+  init_dynamic_string_checked(&ds_tmp, "",
                       ds_str->length + replace_len, 256);
-  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
-  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
-  dynstr_append(&ds_tmp, start + search_len);
-  dynstr_set(ds_str, ds_tmp.str);
+  dynstr_append_mem_checked(&ds_tmp, ds_str->str, start - ds_str->str);
+  dynstr_append_mem_checked(&ds_tmp, replace_str, replace_len);
+  dynstr_append_checked(&ds_tmp, start + search_len);
+  dynstr_set_checked(ds_str, ds_tmp.str);
   dynstr_free(&ds_tmp);
   return 0;
 }
@@ -3533,10 +3564,7 @@
 
   my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
   if (mysql_query_with_error_report(mysql, &table_res, query))
-  {
-    safe_exit(EX_MYSQLERR);
     DBUG_RETURN(0);
-  }
 
   /* Check if this is a view */
   field= mysql_fetch_field_direct(table_res, 0);
@@ -3550,10 +3578,8 @@
   if (path)
   {
     if (!(sql_file= open_sql_file_for_table(table)))
-    {
-      safe_exit(EX_MYSQLERR);
       DBUG_RETURN(1);
-    }
+
     write_header(sql_file, db);
   }
 
@@ -3599,14 +3625,14 @@
     /* Save the result of SHOW CREATE TABLE in ds_view */
     row= mysql_fetch_row(table_res);
     lengths= mysql_fetch_lengths(table_res);
-    init_dynamic_string(&ds_view, row[1], lengths[1] + 1, 1024);
+    init_dynamic_string_checked(&ds_view, row[1], lengths[1] + 1, 1024);
     mysql_free_result(table_res);
 
     /* Get the result from "select ... information_schema" */
     if (!(table_res= mysql_store_result(mysql)) ||
         !(row= mysql_fetch_row(table_res)))
     {
-      safe_exit(EX_MYSQLERR);
+      DB_error(mysql, "when trying to save the result of SHOW CREATE TABLE in ds_view.");
       DBUG_RETURN(1);
     }
 
@@ -3676,6 +3702,45 @@
     my_fclose(sql_file, MYF(MY_WME));
   }
   DBUG_RETURN(0);
+}
+
+/*
+  The following functions are wrappers for the dynamic string functions
+  and if they fail, the wrappers will terminate the current process.
+*/
+
+#define DYNAMIC_STR_ERROR_MSG "Couldn't perform DYNAMIC_STRING operation"
+
+static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
+			    uint init_alloc, uint alloc_increment)
+{
+  if (init_dynamic_string(str, init_str, init_alloc, alloc_increment))
+    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src)
+{
+  if (dynstr_append(dest, src))
+    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str)
+{
+  if (dynstr_set(str, init_str))
+    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
+			  uint length)
+{
+  if (dynstr_append_mem(str, append, length))
+    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size)
+{
+  if (dynstr_realloc(str, additional_size))
+    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 }
 
 

Thread
bk commit into 5.0 tree (Damien:1.2400) BUG#26346damien16 Mar