mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 13:22:07 +00:00
fix(crypto): fix segfault in X509Certificate.issuerCertificate getter (#27025)
This commit is contained in:
@@ -560,6 +560,8 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_infoAccess, (JSGlobalObject * g
|
||||
return JSValue::encode(jsUndefined());
|
||||
|
||||
BUF_MEM* bptr = bio;
|
||||
if (!bptr)
|
||||
return JSValue::encode(jsUndefined());
|
||||
return JSValue::encode(undefinedIfEmpty(jsString(vm, String::fromUTF8(std::span(bptr->data, bptr->length)))));
|
||||
}
|
||||
|
||||
@@ -602,20 +604,10 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_issuerCertificate, (JSGlobalObj
|
||||
return {};
|
||||
}
|
||||
|
||||
auto issuerCert = thisObject->view().getIssuer();
|
||||
if (!issuerCert)
|
||||
return JSValue::encode(jsUndefined());
|
||||
|
||||
auto bio = issuerCert.get();
|
||||
|
||||
BUF_MEM* bptr = nullptr;
|
||||
BIO_get_mem_ptr(bio, &bptr);
|
||||
std::span<const uint8_t> span(reinterpret_cast<const uint8_t*>(bptr->data), bptr->length);
|
||||
auto* zigGlobalObject = defaultGlobalObject(globalObject);
|
||||
auto* structure = zigGlobalObject->m_JSX509CertificateClassStructure.get(zigGlobalObject);
|
||||
auto jsIssuerCert = JSX509Certificate::create(vm, structure, globalObject, span);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsIssuerCert);
|
||||
// issuerCertificate is only available when the certificate was obtained from
|
||||
// a TLS connection with a peer certificate chain. For certificates parsed
|
||||
// directly from PEM/DER data, it is always undefined (matching Node.js behavior).
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_publicKey, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
|
||||
|
||||
31
test/regression/issue/27025.test.ts
Normal file
31
test/regression/issue/27025.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { X509Certificate } from "crypto";
|
||||
import { readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
const certPem = readFileSync(join(import.meta.dir, "../../js/node/test/fixtures/keys/agent1-cert.pem"));
|
||||
|
||||
test("issuerCertificate should return undefined for directly-parsed certificates without crashing", () => {
|
||||
const cert = new X509Certificate(certPem);
|
||||
|
||||
// issuerCertificate is only populated for certificates obtained from TLS
|
||||
// connections with a peer certificate chain. For directly parsed certs,
|
||||
// it should be undefined (matching Node.js behavior).
|
||||
expect(cert.issuerCertificate).toBeUndefined();
|
||||
});
|
||||
|
||||
test("X509Certificate properties should not crash on valid certificates", () => {
|
||||
const cert = new X509Certificate(certPem);
|
||||
|
||||
// These should all work without segfaulting
|
||||
expect(cert.subject).toBeDefined();
|
||||
expect(cert.issuer).toBeDefined();
|
||||
expect(cert.validFrom).toBeDefined();
|
||||
expect(cert.validTo).toBeDefined();
|
||||
expect(cert.fingerprint).toBeDefined();
|
||||
expect(cert.fingerprint256).toBeDefined();
|
||||
expect(cert.fingerprint512).toBeDefined();
|
||||
expect(cert.serialNumber).toBeDefined();
|
||||
expect(cert.raw).toBeInstanceOf(Uint8Array);
|
||||
expect(cert.ca).toBe(false);
|
||||
});
|
||||
Reference in New Issue
Block a user