List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:January 12 2011 4:13pm
Subject:bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3521) Bug#57450
View as plain text  
#At file:///Users/shulga/projects/mysql/5.1-bugteam-bug57450/ based on revid:azundris@stripped

 3521 Dmitry Shulga	2011-01-12
      Fixed bug#57450	- mysql client enter in an infinite loop
      if the standard input is a directory.
      
      The problem is that mysql monitor try to read from stdin without
      checking input source type.
      
      The solution is to stop reading data from standard input if a call
      to read(2) failed.
      
      A new output parameter was introduced into functions batch_readline()
      and intern_read_line() in order to differentiate between
      cases of getting EOF and getting error on standard input.
      
      A new test case was added into mysql.test.
     @ client/my_readline.h
        Added third output parameter into batch_readline.
     @ client/mysql.cc
        read_and_execute() was modified: set status.exit_status to 1
        when a call to batch_readline() returns NULL and
        valriable have_sys_err is true.
     @ client/readline.cc
        intern_read_line() was modified: cancel reading from input if
        fill_buffer() returns -1, e.g. if call to read failed.

    modified:
      client/my_readline.h
      client/mysql.cc
      client/readline.cc
      mysql-test/t/mysql.test
=== modified file 'client/my_readline.h'
--- a/client/my_readline.h	2009-03-18 08:27:49 +0000
+++ b/client/my_readline.h	2011-01-12 16:12:53 +0000
@@ -29,5 +29,6 @@ typedef struct st_line_buffer
 
 extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
 extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
-extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated);
+extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated,
+                            bool *have_sys_err);
 extern void batch_readline_end(LINE_BUFFER *buffer);

=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2010-10-19 22:36:59 +0000
+++ b/client/mysql.cc	2011-01-12 16:12:53 +0000
@@ -1874,12 +1874,13 @@ static int read_and_execute(bool interac
   COMMANDS *com;
   bool truncated= 0;
   status.exit_status=1;
-  
+  bool have_sys_err= false;
+
   for (;;)
   {
     if (!interactive)
     {
-      line=batch_readline(status.line_buff, &truncated);
+      line=batch_readline(status.line_buff, &truncated, &have_sys_err);
       /*
         Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
         Editors like "notepad" put this marker in
@@ -1953,9 +1954,12 @@ static int read_and_execute(bool interac
       if (opt_outfile && line)
 	fprintf(OUTFILE, "%s\n", line);
     }
-    if (!line)					// End of file
+    if (!line)				// End of file or system error
     {
-      status.exit_status=0;
+      if (have_sys_err)
+        status.exit_status= 1;
+      else
+        status.exit_status= 0;
       break;
     }
 

=== modified file 'client/readline.cc'
--- a/client/readline.cc	2009-03-18 08:27:49 +0000
+++ b/client/readline.cc	2011-01-12 16:12:53 +0000
@@ -24,7 +24,8 @@ static bool init_line_buffer(LINE_BUFFER
 			    ulong max_size);
 static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
 static size_t fill_buffer(LINE_BUFFER *buffer);
-static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated);
+static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length,
+                              bool *truncated, bool *have_sys_err);
 
 
 LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
@@ -42,13 +43,15 @@ LINE_BUFFER *batch_readline_init(ulong m
 }
 
 
-char *batch_readline(LINE_BUFFER *line_buff, bool *truncated)
+char *batch_readline(LINE_BUFFER *line_buff, bool *truncated,
+                     bool *have_sys_err)
 {
   char *pos;
   ulong out_length;
   DBUG_ASSERT(truncated != NULL);
 
-  if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
+  if (!(pos=intern_read_line(line_buff,&out_length, truncated,
+                             have_sys_err)))
     return 0;
   if (out_length && pos[out_length-1] == '\n')
     if (--out_length && pos[out_length-1] == '\r')  /* Remove '\n' */
@@ -162,7 +165,7 @@ static size_t fill_buffer(LINE_BUFFER *b
     if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
 					      buffer->bufread+1,
 					      MYF(MY_WME | MY_FAE))))
-      return (uint) -1;
+      return (size_t) -1;
     buffer->start_of_line=buffer->buffer+start_offset;
     buffer->end=buffer->buffer+bufbytes;
   }
@@ -199,7 +202,8 @@ static size_t fill_buffer(LINE_BUFFER *b
 
 
 
-char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated)
+char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length,
+                       bool *truncated, bool *have_sys_err)
 {
   char *pos;
   size_t length;
@@ -214,15 +218,21 @@ char *intern_read_line(LINE_BUFFER *buff
     if (pos == buffer->end)
     {
       /*
-        fill_buffer() can return 0 either on EOF in which case we abort
-        or when the internal buffer has hit the size limit. In the latter case
-        return what we have read so far and signal string truncation.
+        fill_buffer() can return 0 either on EOF (or if system error
+        was occurred) in which case we abort or when the internal
+        buffer has hit the size limit. In the latter case return what
+        we have read so far and signal string truncation.
       */
-      if (!(length=fill_buffer(buffer)) || length == (uint) -1)
+      if (!(length=fill_buffer(buffer)))
       {
         if (buffer->eof)
           DBUG_RETURN(0);
       }
+      else if (length == (size_t) -1)
+      {
+        *have_sys_err= true;
+        DBUG_RETURN(0);
+      }
       else
         continue;
       pos--;					/* break line here */

=== modified file 'mysql-test/t/mysql.test'
--- a/mysql-test/t/mysql.test	2009-12-17 20:06:36 +0000
+++ b/mysql-test/t/mysql.test	2011-01-12 16:12:53 +0000
@@ -412,5 +412,11 @@ drop table t1;
 --echo
 --exec $MYSQL --skip-column-names --vertical test -e "select 1 as a"
 
+#
+# Bug#57450: mysql client enter in an infinite loop if the standard input is a directory
+#
+--error 1
+--exec $MYSQL < .
+
 --echo
 --echo End of tests


Attachment: [text/bzr-bundle] bzr/dmitry.shulga@oracle.com-20110112161253-1ffh08e6dxdul80f.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3521) Bug#57450Dmitry Shulga12 Jan
  • Re: bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3521)Bug#57450Davi Arnaut17 Jan
    • Re: bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3521) Bug#57450Dmitry Shulga19 Jan