[glib] gio: Don't allow skipping past the end of GLocalFileInputStream



commit 89f961583580b16b5b67b2138d609ffd52f59c75
Author: Ross Lagerwall <rosslagerwall gmail com>
Date:   Tue Oct 29 06:02:59 2013 +0200

    gio: Don't allow skipping past the end of GLocalFileInputStream
    
    The overridden implementation of the skip method for
    GLocalFileInputStream allows skipping past the end of the file which is
    inconsistent with the documentation.  Prevent this by first seeking to
    the end of the file and then seeking backwards from there as much as
    is necessary.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=711048

 gio/glocalfileinputstream.c |   23 +++++++++++++++++++----
 gio/tests/readwrite.c       |   12 ++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)
---
diff --git a/gio/glocalfileinputstream.c b/gio/glocalfileinputstream.c
index 5d4acf6..2c32353 100644
--- a/gio/glocalfileinputstream.c
+++ b/gio/glocalfileinputstream.c
@@ -185,7 +185,7 @@ g_local_file_input_stream_skip (GInputStream  *stream,
                                GCancellable  *cancellable,
                                GError       **error)
 {
-  off_t res, start;
+  off_t start, end;
   GLocalFileInputStream *file;
 
   file = G_LOCAL_FILE_INPUT_STREAM (stream);
@@ -205,8 +205,8 @@ g_local_file_input_stream_skip (GInputStream  *stream,
       return -1;
     }
   
-  res = lseek (file->priv->fd, count, SEEK_CUR);
-  if (res == -1)
+  end = lseek (file->priv->fd, 0, SEEK_END);
+  if (end == -1)
     {
       int errsv = errno;
 
@@ -217,7 +217,22 @@ g_local_file_input_stream_skip (GInputStream  *stream,
       return -1;
     }
 
-  return res - start;
+  if (end - start > count)
+    {
+      end = lseek (file->priv->fd, count - (end - start), SEEK_CUR);
+      if (end == -1)
+       {
+         int errsv = errno;
+
+         g_set_error (error, G_IO_ERROR,
+                      g_io_error_from_errno (errsv),
+                      _("Error seeking in file: %s"),
+                      g_strerror (errsv));
+         return -1;
+       }
+    }
+
+  return end - start;
 }
 
 static gboolean
diff --git a/gio/tests/readwrite.c b/gio/tests/readwrite.c
index 0484d18..5ac2f6f 100644
--- a/gio/tests/readwrite.c
+++ b/gio/tests/readwrite.c
@@ -66,6 +66,18 @@ verify_iostream (GFileIOStream *file_iostream)
                         10, G_SEEK_SET,
                         NULL, NULL);
 
+  res = g_input_stream_skip (in, 5, NULL, NULL);
+  g_assert (res == 5);
+  verify_pos (iostream, 15);
+
+  res = g_input_stream_skip (in, 10000, NULL, NULL);
+  g_assert (res == strlen (original_data) - 15);
+  verify_pos (iostream, strlen (original_data));
+
+  res = g_seekable_seek (G_SEEKABLE (iostream),
+                        10, G_SEEK_SET,
+                        NULL, NULL);
+
   verify_pos (iostream, 10);
 
   res = g_output_stream_write_all (out, new_data, strlen (new_data),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]