Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,33 @@ internal static X509Certificate2[] X509ChainGetCertificates(SafeX509ChainContext
var certPtrs = new IntPtr[count];

int res = Interop.AndroidCrypto.X509ChainGetCertificates(ctx, certPtrs, certPtrs.Length);
if (res == 0)
throw new CryptographicException();

Debug.Assert(res <= certPtrs.Length);

var certs = new X509Certificate2[certPtrs.Length];
for (int i = 0; i < res; i++)
try
{
if (res == 0)
throw new CryptographicException();

Debug.Assert(res <= certPtrs.Length);

for (int i = 0; i < res; i++)
{
// X509Certificate2 duplicates these JNI global refs; the native-returned refs remain caller-owned.
certs[i] = new X509Certificate2(certPtrs[i]);
}
}
finally
{
certs[i] = new X509Certificate2(certPtrs[i]);
// The native side can populate part of certPtrs and then fail (returning 0) if a JNI
// exception is thrown mid-loop, so release every non-null entry rather than only the
// first `res` entries.
for (int i = 0; i < certPtrs.Length; i++)
{
if (certPtrs[i] != IntPtr.Zero)
{
Interop.JObjectLifetime.DeleteGlobalReference(certPtrs[i]);
}
}
}

if (res == certPtrs.Length)
Expand Down
Loading