Commit 7f4ac80224 for openssl.org
commit 7f4ac8022492a54aedd0100af4e624600d60c590
Author: Mounir IDRASSI <mounir.idrassi@idrix.fr>
Date: Wed Jul 1 23:43:18 2026 +0900
test: cover empty directoryName name constraints
Add NAME_CONSTRAINTS_check() coverage for empty directoryName
subtrees in both excluded and permitted constraints.
The tests assert the existing results in ordinary builds and catch
the NULL memcmp() argument when run under UBSan.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Daniel Kubec <kubec@openssl.foundation>
MergeDate: Fri Jul 10 15:51:03 2026
(Merged from https://github.com/openssl/openssl/pull/31814)
diff --git a/test/x509_test.c b/test/x509_test.c
index e9529148d4..a5beb7ca2f 100644
--- a/test/x509_test.c
+++ b/test/x509_test.c
@@ -550,6 +550,101 @@ err:
return ret;
}
+/*
+ * nameConstraints extnValue contents with one empty directoryName subtree.
+ * Empty X509_NAME has canon_enc == NULL / canon_enclen == 0.
+ *
+ * SEQUENCE { [0|1] { SEQUENCE { [4] { SEQUENCE {} } } } }
+ */
+static const unsigned char nc_excluded_empty_dirname[] = {
+ 0x30, 0x08, 0xa1, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00
+};
+static const unsigned char nc_permitted_empty_dirname[] = {
+ 0x30, 0x08, 0xa0, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00
+};
+
+/* Decode a raw nameConstraints extnValue into a NAME_CONSTRAINTS object. */
+static NAME_CONSTRAINTS *nc_empty_dirname_from_der(const unsigned char *der,
+ unsigned int der_len)
+{
+ NAME_CONSTRAINTS *nc = NULL;
+ ASN1_OCTET_STRING *os = NULL;
+ X509_EXTENSION *ext = NULL;
+
+ os = ASN1_OCTET_STRING_new();
+ if (!TEST_ptr(os)
+ || !TEST_true(ASN1_OCTET_STRING_set(os, der, der_len)))
+ goto end;
+ ext = X509_EXTENSION_create_by_NID(NULL, NID_name_constraints,
+ 1 /* critical */, os);
+ if (!TEST_ptr(ext))
+ goto end;
+ nc = X509V3_EXT_d2i(ext);
+
+end:
+ X509_EXTENSION_free(ext);
+ ASN1_OCTET_STRING_free(os);
+ return nc;
+}
+
+/* Build a minimal certificate with a non-empty subject DN. */
+static X509 *nc_empty_dirname_subject(const char *cn)
+{
+ X509 *x = NULL;
+ X509_NAME *nm = NULL;
+
+ if (!TEST_ptr(x = X509_new()))
+ goto err;
+ nm = X509_NAME_new();
+ if (!TEST_ptr(nm)
+ || !TEST_true(X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC,
+ (const unsigned char *)cn, -1, -1, 0))
+ || !TEST_true(X509_set_subject_name(x, nm)))
+ goto err;
+ X509_NAME_free(nm);
+ return x;
+
+err:
+ X509_NAME_free(nm);
+ X509_free(x);
+ return NULL;
+}
+
+/* Check an empty directoryName constraint against a non-empty subject DN. */
+static int nc_check_empty_dirname(const unsigned char *der, unsigned int der_len,
+ int expected)
+{
+ int ok = 0;
+ NAME_CONSTRAINTS *nc = NULL;
+ X509 *x = NULL;
+
+ if (!TEST_ptr(nc = nc_empty_dirname_from_der(der, der_len))
+ || !TEST_ptr(x = nc_empty_dirname_subject("leaf.example"))
+ || !TEST_int_eq(NAME_CONSTRAINTS_check(x, nc), expected))
+ goto end;
+
+ ok = 1;
+
+end:
+ X509_free(x);
+ NAME_CONSTRAINTS_free(nc);
+ return ok;
+}
+
+/* Empty excluded directoryName matches the subject DN: excluded violation. */
+static int test_nc_empty_dirname_excluded(void)
+{
+ return nc_check_empty_dirname(nc_excluded_empty_dirname,
+ sizeof(nc_excluded_empty_dirname), X509_V_ERR_EXCLUDED_VIOLATION);
+}
+
+/* Empty permitted directoryName matches the subject DN: permitted. */
+static int test_nc_empty_dirname_permitted(void)
+{
+ return nc_check_empty_dirname(nc_permitted_empty_dirname,
+ sizeof(nc_permitted_empty_dirname), X509_V_OK);
+}
+
OPT_TEST_DECLARE_USAGE("<pss-self-signed-cert.pem>\n")
int setup_tests(void)
@@ -591,6 +686,8 @@ int setup_tests(void)
ADD_TEST(test_drop_empty_csr_keyids);
ADD_TEST(test_rsaesoaep_spki);
ADD_TEST(test_x509_verify_with_new);
+ ADD_TEST(test_nc_empty_dirname_excluded);
+ ADD_TEST(test_nc_empty_dirname_permitted);
return 1;
}