From fa10d1e97da45203f509e9c9e95eb82cb245928b Mon Sep 17 00:00:00 2001 From: pjt33 Date: Wed, 26 Feb 2025 12:23:35 +0100 Subject: [PATCH] Fix SlicedStream.Seek(offset, SeekOrigin.End) (#18313) * Fix SlicedStream.Seek(offset, SeekOrigin.End) This fixes https://github.com/AvaloniaUI/Avalonia/issues/13604 The offset _from is applied in set_Position, so applying it also in Seek mispositions the stream. ZipArchive exposes the problem by seeking to the end to read the table of contents. * Add tests for SlicedStream --------- Co-authored-by: Julien Lebosquain --- .../Platform/Internal/SlicedStream.cs | 2 +- .../Platform/SlicedStreamTests.cs | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/Avalonia.Base.UnitTests/Platform/SlicedStreamTests.cs diff --git a/src/Avalonia.Base/Platform/Internal/SlicedStream.cs b/src/Avalonia.Base/Platform/Internal/SlicedStream.cs index 124c248aa8..86a8dd5da9 100644 --- a/src/Avalonia.Base/Platform/Internal/SlicedStream.cs +++ b/src/Avalonia.Base/Platform/Internal/SlicedStream.cs @@ -29,7 +29,7 @@ internal class SlicedStream : Stream if (origin == SeekOrigin.Begin) Position = offset; if (origin == SeekOrigin.End) - Position = _from + Length + offset; + Position = Length + offset; if (origin == SeekOrigin.Current) Position = Position + offset; return Position; diff --git a/tests/Avalonia.Base.UnitTests/Platform/SlicedStreamTests.cs b/tests/Avalonia.Base.UnitTests/Platform/SlicedStreamTests.cs new file mode 100644 index 0000000000..dbcabf997c --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Platform/SlicedStreamTests.cs @@ -0,0 +1,29 @@ +using System.IO; +using Avalonia.Platform.Internal; +using Xunit; + +namespace Avalonia.Base.UnitTests; + +public class SlicedStreamTests +{ + [Theory] + [InlineData(2, SeekOrigin.Begin, 22, 2, 9)] + [InlineData(2, SeekOrigin.Current, 22, 17, 24)] + [InlineData(-2, SeekOrigin.End, 22, 40, 47)] + public void Seek_Works( + long offset, + SeekOrigin origin, + long startingUnderlyingPosition, + long expectedPosition, + long expectedUnderlyingPosition) + { + var memoryStream = new MemoryStream(new byte[1024]); + var slicedStream = new SlicedStream(memoryStream, 7, 42); + memoryStream.Position = startingUnderlyingPosition; + + slicedStream.Seek(offset, origin); + + Assert.Equal(expectedPosition, slicedStream.Position); + Assert.Equal(expectedUnderlyingPosition, memoryStream.Position); + } +}