[前][次][番号順一覧][スレッド一覧]

ruby-changes:23277

From: naruse <ko1@a...>
Date: Sun, 15 Apr 2012 03:02:13 +0900 (JST)
Subject: [ruby-changes:23277] naruse:r35328 (ruby_1_9_3): merge revision(s) 34785,35095,35098,35111,35152: [Backport #6294]

naruse	2012-04-15 03:02:01 +0900 (Sun, 15 Apr 2012)

  New Revision: 35328

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35328

  Log:
    merge revision(s) 34785,35095,35098,35111,35152: [Backport #6294]
    
    * io.c (set_binary_mode_with_seek_cur): reorder function qualifiers.
    * test/ruby/test_io.rb (TestIO#test_pos_with_getc): added.
      see [Bug #6179][ruby-core:43518]
    
    * test/ruby/test_io.rb (TestIO#test_pos_with_getc): updated.
      see [ruby-core:43550]
    
    * io.c (static int io_fflush): add the definition.
      Use it in set_binary_mode_with_seek_cur().
    
    * io.c (set_binary_mode_with_seek_cur): refactoring to split the
      content into io_unread(). Fix the possibility of buffer overflow.
    
    * io.c (io_unread): add new implementation for Windows. Previous one
      caused invalid cursor position using IO#pos with OS text mode. New
      one fixes the bug.
    
    * test/ruby/test_io_m17n.rb
      (TestIO_M17N#test_pos_dont_move_cursor_position): add a test for
      above bug.
      [ruby-core:43497] [Bug #6179]
    
    * io.c (io_unread): fixed memory leak.  report by nagachika via IRC.

  Modified files:
    branches/ruby_1_9_3/ChangeLog
    branches/ruby_1_9_3/io.c
    branches/ruby_1_9_3/test/ruby/test_io.rb
    branches/ruby_1_9_3/test/ruby/test_io_m17n.rb
    branches/ruby_1_9_3/version.h

Index: ruby_1_9_3/ChangeLog
===================================================================
--- ruby_1_9_3/ChangeLog	(revision 35327)
+++ ruby_1_9_3/ChangeLog	(revision 35328)
@@ -1,3 +1,34 @@
+Sun Apr 15 03:00:54 2012  NAKAMURA Usaku  <usa@r...>
+
+	* io.c (io_unread): fixed memory leak.  report by nagachika via IRC.
+
+Sun Apr 15 03:00:54 2012  Hiroshi Shirosaki  <h.shirosaki@g...>
+
+	* io.c (static int io_fflush): add the definition.
+	  Use it in set_binary_mode_with_seek_cur().
+
+	* io.c (set_binary_mode_with_seek_cur): refactoring to split the
+	  content into io_unread(). Fix the possibility of buffer overflow.
+
+	* io.c (io_unread): add new implementation for Windows. Previous one
+	  caused invalid cursor position using IO#pos with OS text mode. New
+	  one fixes the bug.
+
+	* test/ruby/test_io_m17n.rb
+	  (TestIO_M17N#test_pos_dont_move_cursor_position): add a test for
+	  above bug.
+	  [ruby-core:43497] [Bug #6179]
+
+Sun Apr 15 03:00:54 2012  NAKAMURA Usaku  <usa@r...>
+
+	* test/ruby/test_io.rb (TestIO#test_pos_with_getc): updated.
+	  see [ruby-core:43550]
+
+Sun Apr 15 03:00:54 2012  NAKAMURA Usaku  <usa@r...>
+
+	* test/ruby/test_io.rb (TestIO#test_pos_with_getc): added.
+	  see [Bug #6179][ruby-core:43518]
+
 Wed Apr 11 16:22:16 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/-test-/add_suffix/bug.c (ruby_add_suffix): no static
Index: ruby_1_9_3/io.c
===================================================================
--- ruby_1_9_3/io.c	(revision 35327)
+++ ruby_1_9_3/io.c	(revision 35328)
@@ -222,6 +222,7 @@
 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
 
 static int io_fflush(rb_io_t *);
+static rb_io_t *flush_before_seek(rb_io_t *fptr);
 
 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
@@ -257,38 +258,47 @@
 	(ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
     }\
 } while(0)
+
 /*
- * We use io_seek to back cursor position when changing mode from text to binary,
- * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
- * conversion for working properly with mode change.
+ * IO unread with taking care of removed '\r' in text mode.
  */
-/*
- * Return previous translation mode.
- */
-inline static int set_binary_mode_with_seek_cur(rb_io_t *fptr) {
+static void
+io_unread(rb_io_t *fptr)
+{
     off_t r, pos;
     ssize_t read_size;
     long i;
     long newlines = 0;
     long extra_max;
     char *p;
+    char *buf;
 
-    if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
-
+    rb_io_check_closed(fptr);
     if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
-	return setmode(fptr->fd, O_BINARY);
+	return;
     }
 
-    if (io_fflush(fptr) < 0) {
-	rb_sys_fail(0);
+    errno = 0;
+    if (!rb_w32_fd_is_text(fptr->fd)) {
+	r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
+	if (r < 0 && errno) {
+	    if (errno == ESPIPE)
+		fptr->mode |= FMODE_DUPLEX;
+	    return;
+	}
+
+	fptr->rbuf.off = 0;
+	fptr->rbuf.len = 0;
+	return;
     }
-    errno = 0;
+
     pos = lseek(fptr->fd, 0, SEEK_CUR);
     if (pos < 0 && errno) {
 	if (errno == ESPIPE)
 	    fptr->mode |= FMODE_DUPLEX;
-	return setmode(fptr->fd, O_BINARY);
+	return;
     }
+
     /* add extra offset for removed '\r' in rbuf */
     extra_max = (long)(pos - fptr->rbuf.len);
     p = fptr->rbuf.ptr + fptr->rbuf.off;
@@ -297,6 +307,8 @@
 	if (extra_max == newlines) break;
 	p++;
     }
+
+    buf = ALLOC_N(char, fptr->rbuf.len + newlines);
     while (newlines >= 0) {
 	r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
 	if (newlines == 0) break;
@@ -304,8 +316,9 @@
 	    newlines--;
 	    continue;
 	}
-	read_size = _read(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.len + newlines);
+	read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
 	if (read_size < 0) {
+	    free(buf);
 	    rb_sys_fail_path(fptr->pathv);
 	}
 	if (read_size == fptr->rbuf.len) {
@@ -316,8 +329,28 @@
 	    newlines--;
 	}
     }
+    free(buf);
     fptr->rbuf.off = 0;
     fptr->rbuf.len = 0;
+    return;
+}
+
+/*
+ * We use io_seek to back cursor position when changing mode from text to binary,
+ * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
+ * conversion for working properly with mode change.
+ *
+ * Return previous translation mode.
+ */
+static inline int
+set_binary_mode_with_seek_cur(rb_io_t *fptr)
+{
+    if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
+
+    if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
+	return setmode(fptr->fd, O_BINARY);
+    }
+    flush_before_seek(fptr);
     return setmode(fptr->fd, O_BINARY);
 }
 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
@@ -448,6 +481,7 @@
     return rb_io_check_io(io);
 }
 
+#if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
 static void
 io_unread(rb_io_t *fptr)
 {
@@ -467,6 +501,7 @@
     fptr->rbuf.len = 0;
     return;
 }
+#endif
 
 static rb_encoding *io_input_encoding(rb_io_t *fptr);
 
Index: ruby_1_9_3/version.h
===================================================================
--- ruby_1_9_3/version.h	(revision 35327)
+++ ruby_1_9_3/version.h	(revision 35328)
@@ -1,10 +1,10 @@
 #define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 179
+#define RUBY_PATCHLEVEL 180
 
-#define RUBY_RELEASE_DATE "2012-04-11"
+#define RUBY_RELEASE_DATE "2012-04-15"
 #define RUBY_RELEASE_YEAR 2012
 #define RUBY_RELEASE_MONTH 4
-#define RUBY_RELEASE_DAY 11
+#define RUBY_RELEASE_DAY 15
 
 #include "ruby/version.h"
 
Index: ruby_1_9_3/test/ruby/test_io_m17n.rb
===================================================================
--- ruby_1_9_3/test/ruby/test_io_m17n.rb	(revision 35327)
+++ ruby_1_9_3/test/ruby/test_io_m17n.rb	(revision 35328)
@@ -2347,4 +2347,19 @@
     }
     assert_equal(paths.map(&:encoding), encs, bug6072)
   end
+
+  def test_pos_dont_move_cursor_position
+    bug6179 = '[ruby-core:43497]'
+    with_tmpdir {
+      str = "line one\r\nline two\r\nline three\r\n"
+      generate_file("tmp", str)
+      open("tmp", "r") do |f|
+        assert_equal("line one\n", f.readline)
+        assert_equal(10, f.pos, bug6179)
+        assert_equal("line two\n", f.readline, bug6179)
+        assert_equal(20, f.pos, bug6179)
+        assert_equal("line three\n", f.readline, bug6179)
+      end
+    }
+  end if /mswin|mingw/ =~ RUBY_PLATFORM
 end
Index: ruby_1_9_3/test/ruby/test_io.rb
===================================================================
--- ruby_1_9_3/test/ruby/test_io.rb	(revision 35327)
+++ ruby_1_9_3/test/ruby/test_io.rb	(revision 35328)
@@ -1307,6 +1307,30 @@
     end
   end
 
+  def test_pos_with_getc
+    bug6179 = '[ruby-core:43497]'
+    t = make_tempfile
+    ["", "t", "b"].each do |mode|
+      open(t.path, "w#{mode}") do |f|
+        f.write "0123456789\n"
+      end
+
+      open(t.path, "r#{mode}") do |f|
+        assert_equal 0, f.pos, "mode=r#{mode}"
+        assert_equal '0', f.getc, "mode=r#{mode}"
+        assert_equal 1, f.pos, "mode=r#{mode}"
+        assert_equal '1', f.getc, "mode=r#{mode}"
+        assert_equal 2, f.pos, "mode=r#{mode}"
+        assert_equal '2', f.getc, "mode=r#{mode}"
+        assert_equal 3, f.pos, "mode=r#{mode}"
+        assert_equal '3', f.getc, "mode=r#{mode}"
+        assert_equal 4, f.pos, "mode=r#{mode}"
+        assert_equal '4', f.getc, "mode=r#{mode}"
+      end
+    end
+  end
+
+
   def test_sysseek
     t = make_tempfile
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]