Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit be8013d

Browse files
committed
Change CreateOpenSslCryptographicException to report the last error, not the first.
1 parent d490291 commit be8013d

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

src/Common/src/Interop/Unix/libcrypto/Interop.ERR.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,48 @@ internal static Exception CreateOpenSslCryptographicException()
3232
const uint ReasonMask = 0x0FFF;
3333
const uint ERR_R_MALLOC_FAILURE = 64 | 1;
3434

35+
// The Windows cryptography library reports error codes through
36+
// Marshal.GetLastWin32Error, which has a single value when the
37+
// function exits, last writer wins.
38+
//
39+
// OpenSSL maintains an error queue. Calls to ERR_get_error read
40+
// values out of the queue in the order that ERR_set_error wrote
41+
// them. Nothing enforces that a single call into an OpenSSL
42+
// function will guarantee at-most one error being set.
43+
//
44+
// In order to maintain parity in how error flows look between the
45+
// Windows code and the OpenSSL-calling code, drain the queue
46+
// whenever an Exception is desired, and report the exception
47+
// related to the last value in the queue.
3548
uint error = ERR_get_error();
36-
uint last = error;
49+
uint lastRead = error;
3750

38-
while (last != 0)
51+
// 0 (there's no named constant) is only returned when the calls
52+
// to ERR_get_error exceed the calls to ERR_set_error.
53+
while (lastRead != 0)
3954
{
40-
last = ERR_get_error();
55+
error = lastRead;
56+
lastRead = ERR_get_error();
4157
}
4258

59+
// If we're in an error flow which results in an Exception, but
60+
// no calls to ERR_set_error were made, throw the unadorned
61+
// CryptographicException.
4362
if (error == 0)
4463
{
4564
return new CryptographicException();
4665
}
4766

67+
// Inline version of the ERR_GET_REASON macro.
4868
uint reason = error & ReasonMask;
4969

5070
if (reason == ERR_R_MALLOC_FAILURE)
5171
{
5272
return new OutOfMemoryException();
5373
}
5474

75+
// If there was an error code, and it wasn't something handled specially,
76+
// use the OpenSSL error string as the message to a CryptographicException.
5577
return new CryptographicException(ERR_error_string_n(error));
5678
}
5779

0 commit comments

Comments
 (0)