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 Int32 overflow bug in buffering logic #60459

Merged
merged 5 commits into from
Oct 15, 2021
Merged

Conversation

adamsitnik
Copy link
Member

@adamsitnik adamsitnik commented Oct 15, 2021

fixes #60430

For the following code:

_readPos = (int)(newPos - (oldPos - _readPos));

For a newPos > 4GB and small oldPos and _readPos we had an int32 overflow. Sample C# app to demonstrate the problem:

long oldPos = 10L; // first read started at Position=10
long newPos = (1L << 32) + oldPos; // new position is larger than 4 GB
int _readPos = 5; // 5 bytes were read from the buffer so far
int readPosInteger = (int)(newPos - (oldPos - _readPos));
long readPosLong = (newPos - (oldPos - _readPos));

Console.WriteLine(readPosInteger);
Console.WriteLine(readPosLong);
5
4294967301

It seems to be a very old bug that was always present in BufferedStream and I've copied it to BufferedFileStreamStrategy in 6.0.

1.0 branch:

https://github.com/dotnet/corefx/blob/c74ea81f2ddad07dc05d695d8244fb2ece7e398d/src/System.IO/src/System/IO/BufferedStream.cs#L1053-L1054

Since we are very close to 6.0 release I've focused on making smallest possible change instead of doing a refactor and providing code that would look better but would be harder to review.

@ghost
Copy link

ghost commented Oct 15, 2021

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

Issue Details

fixes #60430

Author: adamsitnik
Assignees: -
Labels:

area-System.IO

Milestone: -

@adamsitnik
Copy link
Member Author

/backport to release/6.0

@github-actions
Copy link
Contributor

Started backporting to release/6.0: https://github.com/dotnet/runtime/actions/runs/1345172097

Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com>
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.

Found only nits, I also tried to see if I could find more overflow issues in BufferedFileStreamStrategy but didn't see any.

Thanks, @adamsitnik.

using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
stream.Seek(position1, SeekOrigin.Begin);
stream.Write(data1, 0, data1.Length);
Copy link
Member

Choose a reason for hiding this comment

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

nit: Use Span-based overloads

Suggested change
stream.Write(data1, 0, data1.Length);
stream.Write(data1);

stream.Write(data1, 0, data1.Length);

stream.Seek(position2, SeekOrigin.Begin);
stream.Write(data2, 0, data2.Length);
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Suggested change
stream.Write(data2, 0, data2.Length);
stream.Write(data2);

Comment on lines +50 to +59
using (var stream = new BufferedStream(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 0)))
{
stream.Seek(position1, SeekOrigin.Begin);
Assert.Equal(buffer.Length, stream.Read(buffer));
Assert.Equal(data1, buffer);

stream.Seek(position2, SeekOrigin.Begin);
Assert.Equal(buffer.Length, stream.Read(buffer));
Assert.Equal(data2, buffer);
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this piece of code should be a separate test in src/libraries/System.IO/tests/BufferedStream/BufferedStreamTests.cs

@jozkee
Copy link
Member

jozkee commented Oct 15, 2021

Merging to keep the backport PR as a clean port of this one i.e: to not have different commits.

CI issue ReadAllBytes_NonSeekableFileStream_InWindows is known #60427.

@jozkee jozkee merged commit ea58ba6 into dotnet:main Oct 15, 2021
@adamsitnik adamsitnik deleted the bug60430 branch October 16, 2021 08:58
@ghost ghost locked as resolved and limited conversation to collaborators Nov 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Disk files larger than 4GB may not be read properly
3 participants