ginputstream: Don’t skip off the end of resizable streams

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
89f9615835), 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 <pwithnall@endlessos.org>

Fixes: #587
This commit is contained in:
Philip Withnall 2021-02-15 14:58:04 +00:00
parent 58dd7a37c9
commit 58c6e0e5d4

View File

@ -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: */