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

[Xamarin.Android.Build.Tasks] make CA2022 an error #9282

Merged
merged 1 commit into from
Sep 5, 2024

Conversation

jonathanpeppers
Copy link
Member

I was building Xamarin.Android.Build.Tasks and noticed some CA2022 warnings that scared me:

src\Xamarin.Android.Build.Tasks\Utilities\AssemblyCompression.cs(77,6):
warning CA2022: Avoid inexact read with 'System.IO.FileStream.Read(byte[], int, int)' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022)
src\Xamarin.Android.Build.Tasks\Utilities\MonoAndroidHelper.cs(186,8):
warning CA2022: Avoid inexact read with 'System.IO.FileStream.Read(byte[], int, int)' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022)

Some cases like this were actually ok:

byte[] publicKey = new byte[stream.Length];
stream.Read (publicKey, 0, publicKey.Length);
// ...
name.PublicKey = SigningHelper.GetPublicKey (publicKey);

Because it uses stream.Length for the byte[] size, we don't need to use the return value of Read().

Looking at another place, however:

sourceBytes = bytePool.Rent (checked((int)fi.Length));
// ...
    fs.Read (sourceBytes, 0, (int)fi.Length);
// ...
destBytes = bytePool.Rent (LZ4Codec.MaximumOutputSize (sourceBytes.Length));

This actually is a bug, as it rents a destBytes array potentially a bit larger than bytes read.

This made me think, we should make CA2022 an error and fix them all.

I also updated MonoAndroidHelper.SizeAndContentFileComparer to just use the Files.HashFile() method. This is probably faster than the previous code, anyway.

I was building Xamarin.Android.Build.Tasks and noticed some CA2022
warnings that scared me:

    src\Xamarin.Android.Build.Tasks\Utilities\AssemblyCompression.cs(77,6):
    warning CA2022: Avoid inexact read with 'System.IO.FileStream.Read(byte[], int, int)' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022)
    src\Xamarin.Android.Build.Tasks\Utilities\MonoAndroidHelper.cs(186,8):
    warning CA2022: Avoid inexact read with 'System.IO.FileStream.Read(byte[], int, int)' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022)

Some cases like this were actually ok:

    byte[] publicKey = new byte[stream.Length];
    stream.Read (publicKey, 0, publicKey.Length);
    // ...
    name.PublicKey = SigningHelper.GetPublicKey (publicKey);

Because it uses `stream.Length` for the `byte[]` size, we don't need
to use the return value of `Read()`.

Looking at another place, however:

    sourceBytes = bytePool.Rent (checked((int)fi.Length));
    // ...
        fs.Read (sourceBytes, 0, (int)fi.Length);
    // ...
    destBytes = bytePool.Rent (LZ4Codec.MaximumOutputSize (sourceBytes.Length));

This actually is a bug, as it rents a `destBytes` array potentially a
bit larger than bytes read.

This made me think, we should make CA2022 an error and fix them all.

I also updated `MonoAndroidHelper.SizeAndContentFileComparer` to just
use the `Files.HashFile()` method. This is probably faster than the
previous code, anyway.
Comment on lines 354 to +356
using (Stream stream = typeof (GenerateResourceDesignerAssembly).Assembly.GetManifestResourceStream ("Resource.Designer.snk")) {
byte[] publicKey = new byte[stream.Length];
stream.Read (publicKey, 0, publicKey.Length);
_ = stream.Read (publicKey, 0, publicKey.Length);
Copy link
Member Author

Choose a reason for hiding this comment

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

This one looks ok, so I just used the _ discard to silence the warning.

Comment on lines -178 to +180
using (var f1 = File.OpenRead (x.FullName)) {
using (var f2 = File.OpenRead (y.FullName)) {
var b1 = new byte [0x1000];
var b2 = new byte [0x1000];
int total = 0;
while (total < x.Length) {
int size = f1.Read (b1, 0, b1.Length);
total += size;
f2.Read (b2, 0, b2.Length);
if (!b1.Take (size).SequenceEqual (b2.Take (size)))
return false;
}
}
}
return true;
string xHash = Files.HashFile (x.FullName);
string yHash = Files.HashFile (y.FullName);
return xHash == yHash;
Copy link
Member Author

Choose a reason for hiding this comment

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

This code should just use Files.HashFile() instead, it's probably faster and easier to read.

Comment on lines -80 to +83
destBytes = bytePool.Rent (LZ4Codec.MaximumOutputSize (sourceBytes.Length));
int encodedLength = LZ4Codec.Encode (sourceBytes, 0, checked((int)fi.Length), destBytes, 0, destBytes.Length, LZ4Level.L12_MAX);
destBytes = bytePool.Rent (LZ4Codec.MaximumOutputSize (bytesRead));
int encodedLength = LZ4Codec.Encode (sourceBytes, 0, bytesRead, destBytes, 0, destBytes.Length, LZ4Level.L12_MAX);
Copy link
Member Author

Choose a reason for hiding this comment

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

So, I think this code previously was renting a larger destBytes byte array than needed. I think we probably had extra empty bytes at the end? Potentially garbage bytes, too?

@jonathanpeppers jonathanpeppers marked this pull request as ready for review September 4, 2024 17:01
@jonathanpeppers
Copy link
Member Author

There are some APK tests that failed with:

System.Net.Http.HttpRequestException : net_http_message_not_success_statuscode_reason, 503, Service Temporarily Unavailable

But I don't think these changes could affect this, so going to merge.

@jonathanpeppers jonathanpeppers merged commit ac8a922 into dotnet:main Sep 5, 2024
54 of 57 checks passed
@jonathanpeppers jonathanpeppers deleted the CA2022 branch September 5, 2024 19:08
@github-actions github-actions bot locked and limited conversation to collaborators Oct 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants