Skip to content

HMACSHA256 randomly throws: System.ArgumentException #100809

Closed
@Ziuan

Description

@Ziuan

Description

When using HMACSHA256.ComputeHash to sign some content, we randomly started to get the error described. The code supplied is heavily simplified to illustrate the problem.

The problem only occurs randomly, when building with Release settings, usually around iteration 10.000.
The non simplified version of the code usually crashes sooner.

We have verified that the problem exists on different computers (macOS and windows).

Using LLDB (macOS) we can see that one thread seems to be handling an unhandled exception pointing in the direction of a memory issue:

thread #2
    frame #0: 0x00007ff80645ca2e libsystem_kernel.dylib`mach_msg2_trap + 10
    frame #1: 0x00007ff80646ae3a libsystem_kernel.dylib`mach_msg2_internal + 84
    frame #2: 0x00007ff806463b62 libsystem_kernel.dylib`mach_msg_overwrite + 653
    frame #3: 0x00007ff80645cd1f libsystem_kernel.dylib`mach_msg + 19
    frame #4: 0x0000000100d02eb8 libcoreclr.dylib`MachMessage::Receive(unsigned int) + 72
    frame #5: 0x0000000100d02122 libcoreclr.dylib`SEHExceptionThread(void*) + 82
    frame #6: 0x00007ff80649c202 libsystem_pthread.dylib`_pthread_start + 99
    frame #7: 0x00007ff806497bab libsystem_pthread.dylib`thread_start + 15

Reproduction Steps

using System.Security.Cryptography;

namespace Identity.Tests;

[TestFixture]
public class SymmetricTests
{
    [Test]
    public void SymmetricEncryptor_Bounds()
    {
        for (var i = 0; i < 100000; i++)
        {
            var signedToken = Enumerable.Repeat((byte)0x20, i).ToArray();
            var ticket = Encrypt(signedToken);
            Assert.That(ticket, Is.Not.Null);
        }
    }

    private static byte[] MergeArrays(int additionalCapacity = 0, params byte[][] arrays)
    {
        var merged = new byte[arrays.Sum(a => a.Length) + additionalCapacity];
        var mergeIndex = 0;
        foreach (var array in arrays) {
            Array.Copy(array, 0, merged, mergeIndex, array.Length);
            mergeIndex += array.Length;
        }
        return merged;
    }

    private static byte[] Encrypt(byte[] toEncrypt)
    {
        const int signatureByteSize = 32;

        var someBytes = Enumerable.Repeat((byte)0x20, 64).ToArray();

        var result = MergeArrays(
            additionalCapacity: signatureByteSize,
            someBytes, toEncrypt);

        using var hmac = new HMACSHA256(someBytes);
        var payloadToSignLength = result.Length - signatureByteSize;
        hmac.ComputeHash(result, 0, payloadToSignLength);

        return result;
    }
}

Expected behavior

One should be able to call Array.Copy, HMACSHA256.ComputeHash, and other framework code without any memory violations.

Actual behavior

System.ArgumentException : Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.

thrown from code: hmac.ComputeHash(result, 0, payloadToSignLength);

Regression?

The issue started happening after migration to .NET8 from .NET6.

Known Workarounds

No known workarounds.

Configuration

Code is running on .NET8 (8.0.202)
System 1:
Windows 11, x64, Ryzen 7950x

System 2:
Apple MacBook Pro, OSX 14.3.1, Intel i9 9980HK

Other information

May be related to calls to GC.KeepAlive(...) calls in the function-calls.

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions