2

Why there is nowhere written that HMACSHA256 can cause System.AccessViolationException when accessed parallelly? The AccessViolationException is super hard to investigate since it cannot be caught by regular try-catch (from .Net 6.0 it cannot be caught at all) and since it is usually thrown elsewhere than where it was caused.

Or even more concerning: why nowhere in documentation is written that (HMAC)SHA256 shall not be reused at all? See example of same strings being hashed differently.


Why I am asking:

Our newly written app was randomly crashing after minutes or hours. In the Windows Event Viewer we then found:

Faulting application name: XXXXX.exe, version: 1.0.0.0, time stamp: 0x62571213
Faulting module name: coreclr.dll, version: 6.0.522.21309, time stamp: 0x625708f4
Exception code: 0xc0000005

Exception code 0xc0000005 is the code of the AccessViolationException. It took days to determine what was causing the problem and we were rather lucky to identify it: since we do a lot of optimization it seemed reasonable to cache the instance of HMACSHA256 and reuse it. Eventually it was accessed by two threads at once and caused the application to crash without any log message (there was only the error code in the Event Viewer, no stacktrace).


Code example producing System.AccessViolationException immediately:

var keyString = "abcdefghijklmnopqrstuvwxyz0123456789";
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(keyString));

var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = 4 };

static IEnumerable<string> EnumerateStrings()
{
    while (true)
    {
        yield return "A short string";
        yield return "Lorem ipsum dolor sit amet, consectetur adipiscing elit ...";
    }
}

Parallel.ForEach(EnumerateStrings(),
                 parallelOptions,
                 theString => hmac.ComputeHash(Encoding.UTF8.GetBytes(theString)));

Disclaimer: I do not require an answer to this question. I just wish somebody has asked exactly this question somewhen before me - it could have given me some clue. I would probably spend less time hitting my head against the wall. Hope it will spare some other heads.

frakon
  • 1,948
  • 2
  • 22
  • 26
  • 1
    If you want to document some important software issue this is probably not the way to do it. You can instead, for example, ask a question like "Why is my multithreaded application using HMACSHA256 generating an access violation?", and then answer the question yourself. – President James K. Polk Nov 16 '22 at 13:42
  • 2
    If documentation doesn't explicitly say that something is thread safe - then you can't assume it is. When when you access something not thread safe from multiple threads then basically anything can happen - the behavior in this case is essentially undefined and as such doesn't need to be documented. You just can't document all of the weird stuff that can happen in this case (in many cases no exceptions are thrown either) – Evk Nov 16 '22 at 14:09
  • @PresidentJamesK.Polk thank you for suggestion, I will do that next time. – frakon Nov 16 '22 at 18:40
  • 1
    @Evk understand, you are right. But everyone does similar mistake occasionally and without any mention of any severe error connected with HMACSHA256 on the internet it takes much longer to find it out. I do not know where this information belongs, maybe not into the documentation. But it would be good know about each unsafe class range of 'undefined' behaviour which it could cause. E.g. List<> is not thread-safe, but it does not cause access violation, nor e.g. OOM. Forgotten Timers do not cause access violation, but can cause OOM when created repeatedly and not disposed, etc. – frakon Nov 16 '22 at 18:53

0 Answers0