From 58c6e0e5d45f545040b799ca676da79690d146b7 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 15 Feb 2021 14:58:04 +0000 Subject: [PATCH] =?UTF-8?q?ginputstream:=20Don=E2=80=99t=20skip=20off=20th?= =?UTF-8?q?e=20end=20of=20resizable=20streams?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default implementation of `g_input_stream_skip()` can skip off the end of resizable streams, as that’s the behaviour of `g_seekable_seek()` for that type of stream. This has previously been fixed for local file input streams (commit 89f961583580b16b5b67b2138d609ffd52f59c75), and a unit test added there. However, the fix should be more generally made in `GInputStream`. This commit reworks an old patch by Dan Winship on https://bugzilla.gnome.org/show_bug.cgi?id=681374, which took that approach. Signed-off-by: Philip Withnall Fixes: #587 --- gio/ginputstream.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/gio/ginputstream.c b/gio/ginputstream.c index 20cece53d..383495162 100644 --- a/gio/ginputstream.c +++ b/gio/ginputstream.c @@ -411,12 +411,41 @@ g_input_stream_real_skip (GInputStream *stream, if (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream))) { + GSeekable *seekable = G_SEEKABLE (stream); + goffset start, end; + gboolean success; + + /* g_seekable_seek() may try to set pending itself */ + stream->priv->pending = FALSE; + + start = g_seekable_tell (seekable); + if (g_seekable_seek (G_SEEKABLE (stream), - count, - G_SEEK_CUR, - cancellable, - NULL)) - return count; + 0, + G_SEEK_END, + cancellable, + NULL)) + { + end = g_seekable_tell (seekable); + g_assert (end >= start); + if (start > G_MAXSIZE - count || start + count > end) + { + stream->priv->pending = TRUE; + return end - start; + } + + success = g_seekable_seek (G_SEEKABLE (stream), + start + count, + G_SEEK_SET, + cancellable, + error); + stream->priv->pending = TRUE; + + if (success) + return count; + else + return -1; + } } /* If not seekable, or seek failed, fall back to reading data: */