Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Position and Seek for MemoryStream with custom origin #88572

Merged
merged 3 commits into from
Aug 21, 2023

Conversation

manandre
Copy link
Contributor

Fixes #88541

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Jul 10, 2023
@ghost
Copy link

ghost commented Jul 10, 2023

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #88541

Author: manandre
Assignees: -
Labels:

area-System.IO

Milestone: -

(10, 5),
(10, 10),
(Array.MaxLength, 0),
(Array.MaxLength, Array.MaxLength)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elgonzo
Copy link

elgonzo commented Jul 10, 2023

Note that this will change the behavior of the MemoryStream.Property and will be in conflict with the current MemoryStream.Position documentation (https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream.position?view=net-8.0#exceptions). If this pull request is accepted, please don't forget to update the MemoryStream.Position documentation accordingly.

@jozkee
Copy link
Member

jozkee commented Aug 17, 2023

@elgonzo @manandre I do believe this is the right approach and we should continue with updating the docs for Seek() and Position accordingly.

@jozkee jozkee added the needs-author-action An issue or pull request that requires more info or actions from the author. label Aug 17, 2023
@ghost ghost removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Aug 18, 2023
using (MemoryStream ms = new MemoryStream(buffer, origin, buffer.Length - origin, true))
{
Seek(mode, ms, int.MaxValue - origin);
Assert.Throws<ArgumentOutOfRangeException>(() => Seek(mode, ms, (long)int.MaxValue - origin + 1));
Copy link
Member

@jozkee jozkee Aug 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please test with an offset of long.MinValue + 1 (uncasted). The check we discussed in https://github.com/dotnet/runtime/pull/88572/files/6880c4d6d148f46a878f929303fd2472e8fbc363#r1297747637 may be there to prevent an overflow after the (int) conversion.

Copy link

@elgonzo elgonzo Aug 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, removing the unchecked(loc + offset) < _origin check was a mistake. Because (int)offset used for calculating tempPosition will just cut the upper 32 bit from the long value, turning certain negative offset values into positive tempPosition values that are equal to or larger than _origin, thus not correctly failing on offset values representing invalid negative positions. For example, with this change, calling Seek(long.MinValue, SeekOrigin.Begin) would lead to tempPosition being equal to the value of _origin and effectively set the stream position to zero instead of throwing, if i am not mistaken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added two Seek calls with long.MinValue + 1 and long.MaxValue - 1 as offset and checked that an exception is correctly raised in all cases.
Indeed I have manually checked that these calls are not always sending an exception when the unchecked(loc + offset) < _origin check is not present.

@manandre manandre force-pushed the memory-stream-seek-max-length branch from 6f31b63 to 23e33c7 Compare August 18, 2023 20:32
Copy link
Member

@jozkee jozkee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@jozkee jozkee merged commit 2d9d468 into dotnet:main Aug 21, 2023
167 of 170 checks passed
@manandre manandre deleted the memory-stream-seek-max-length branch August 21, 2023 18:51
@adamsitnik adamsitnik added this to the 9.0.0 milestone Aug 24, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Sep 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.IO community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

System.IO.MemoryStream: ReadByte() and WriteByte() can throw IndexOutOfRangeException
5 participants