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

IsContentOfFilesTheSame assumes full Stream.Read #825

Closed
KalleOlaviNiemitalo opened this issue Sep 24, 2022 · 1 comment · Fixed by #826
Closed

IsContentOfFilesTheSame assumes full Stream.Read #825

KalleOlaviNiemitalo opened this issue Sep 24, 2022 · 1 comment · Fixed by #826
Assignees
Labels
Milestone

Comments

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Sep 24, 2022

In the Nerdbank.GitVersioning.Tasks.CompareFiles class, the IsContentOfFilesTheSame method calls Stream.Read and assumes that a return value smaller than requested means that it got to the end of the file. As mentioned in #797 (comment), such an assumption is generally a bug. Here though, the stream refers to a regular file, which makes the assumption more likely to hold.

bytesRead = fileStream1.Read(buffer1, 0, buffer1.Length);
if (fileStream2.Read(buffer2, 0, buffer2.Length) != bytesRead)
{
// We should never get here since we compared file lengths, but
// this is a sanity check.
return false;
}

The CompareFiles task is used in Nerdbank.GitVersioning.targets, for deciding whether to run the Copy task. The bug might cause the task to consider the files different when they are actually identical; the target would then needlessly copy the file and cause MSBuild to execute other targets, resulting in a slower incremental build but eventually the correct artefacts.

It might be possible to delete the CompareFiles task altogether and use the SkipUnchangedFiles parameter of the Copy task instead.

<!-- Avoid applying the newly generated AssemblyVersionInfo.cs file to the build
unless it has changed in order to allow for incremental building. -->
<Nerdbank.GitVersioning.Tasks.CompareFiles OriginalItems="$(VersionSourceFile)" NewItems="$(NewVersionSourceFile)">
<Output TaskParameter="AreChanged" PropertyName="AssemblyVersionInfoChanged" />
</Nerdbank.GitVersioning.Tasks.CompareFiles>
<Copy Condition=" '$(AssemblyVersionInfoChanged)' == 'true' " SourceFiles="$(NewVersionSourceFile)" DestinationFiles="$(VersionSourceFile)" />

<!-- Avoid applying the newly generated Version.rc file to the build
unless it has changed in order to allow for incremental building. -->
<Nerdbank.GitVersioning.Tasks.CompareFiles OriginalItems="$(VersionSourceFile)" NewItems="$(NewVersionSourceFile)">
<Output TaskParameter="AreChanged" PropertyName="_NativeVersionInfoChanged" />
</Nerdbank.GitVersioning.Tasks.CompareFiles>
<Copy Condition=" '$(_NativeVersionInfoChanged)' == 'true' " SourceFiles="$(NewVersionSourceFile)" DestinationFiles="$(VersionSourceFile)" />

@AArnott AArnott self-assigned this Sep 25, 2022
@AArnott AArnott added this to the v3.5 milestone Sep 25, 2022
AArnott added a commit that referenced this issue Sep 25, 2022
The task was faulty because it assumed `Stream.Read` would fill the buffer if at all possible. But we also don't need it, since the `Copy` task itself has similar functionality.

Fixes #825
@AArnott AArnott added the bug label Sep 25, 2022
@AArnott
Copy link
Collaborator

AArnott commented Sep 25, 2022

Thanks for finding the bug. It turns out that Copy.SkipUnchangedFiles employs a cheap trick (probably for perf reasons) and will assume that the files are different when the timestamp is different, so it defeats the incremental build preservation that I'm attempting to do. I'll have to fix my task.

AArnott added a commit that referenced this issue Sep 25, 2022
It's a cheap fix, in that it gives up streaming during the compare, but it's far more likely to be accurate than if I tried to maintain streaming while fixing the original bug of assuming that `Stream.Read` will always fill the buffer.

Fixes #825
@AArnott AArnott closed this as completed Sep 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants