1diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c 2index 760e4846a4..f8d4b1b9aa 100644 3--- a/crypto/asn1/bio_ndef.c 4+++ b/crypto/asn1/bio_ndef.c 5@@ -49,12 +49,19 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 6 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 7 void *parg); 8 9+/* 10+ * On success, the returned BIO owns the input BIO as part of its BIO chain. 11+ * On failure, NULL is returned and the input BIO is owned by the caller. 12+ * 13+ * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() 14+ */ 15 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 16 { 17 NDEF_SUPPORT *ndef_aux = NULL; 18 BIO *asn_bio = NULL; 19 const ASN1_AUX *aux = it->funcs; 20 ASN1_STREAM_ARG sarg; 21+ BIO *pop_bio = NULL; 22 23 if (!aux || !aux->asn1_cb) { 24 ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 25@@ -69,21 +76,39 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 26 out = BIO_push(asn_bio, out); 27 if (out == NULL) 28 goto err; 29+ pop_bio = asn_bio; 30 31- BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); 32- BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); 33+ if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0 34+ || BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0 35+ || BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0) 36+ goto err; 37 38 /* 39- * Now let callback prepends any digest, cipher etc BIOs ASN1 structure 40- * needs. 41+ * Now let the callback prepend any digest, cipher, etc., that the BIO's 42+ * ASN1 structure needs. 43 */ 44 45 sarg.out = out; 46 sarg.ndef_bio = NULL; 47 sarg.boundary = NULL; 48 49- if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) 50+ /* 51+ * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the 52+ * middle of some partially built, but not returned BIO chain. 53+ */ 54+ if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) { 55+ /* 56+ * ndef_aux is now owned by asn_bio so we must not free it in the err 57+ * clean up block 58+ */ 59+ ndef_aux = NULL; 60 goto err; 61+ } 62+ 63+ /* 64+ * We must not fail now because the callback has prepended additional 65+ * BIOs to the chain 66+ */ 67 68 ndef_aux->val = val; 69 ndef_aux->it = it; 70@@ -91,11 +116,11 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 71 ndef_aux->boundary = sarg.boundary; 72 ndef_aux->out = out; 73 74- BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); 75- 76 return sarg.ndef_bio; 77 78 err: 79+ /* BIO_pop() is NULL safe */ 80+ (void)BIO_pop(pop_bio); 81 BIO_free(asn_bio); 82 OPENSSL_free(ndef_aux); 83 return NULL; 84diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t 85index 5dc6a3aebe..ec11bfc253 100644 86--- a/test/recipes/80-test_cms.t 87+++ b/test/recipes/80-test_cms.t 88@@ -13,7 +13,7 @@ use warnings; 89 use POSIX; 90 use File::Spec::Functions qw/catfile/; 91 use File::Compare qw/compare_text/; 92-use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file/; 93+use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file with/; 94 use OpenSSL::Test::Utils; 95 96 setup("test_cms"); 97@@ -27,7 +27,7 @@ my $smcont = srctop_file("test", "smcont.txt"); 98 my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) 99 = disabled qw/des dh dsa ec ec2m rc2 zlib/; 100 101-plan tests => 6; 102+plan tests => 7; 103 104 my @smime_pkcs7_tests = ( 105 106@@ -584,3 +584,14 @@ sub check_availability { 107 108 return ""; 109 } 110+ 111+# Check that we get the expected failure return code 112+with({ exit_checker => sub { return shift == 6; } }, 113+ sub { 114+ ok(run(app(['openssl', 'cms', '-encrypt', 115+ '-in', srctop_file("test", "smcont.txt"), 116+ '-stream', '-recip', 117+ srctop_file("test/smime-certs", "badrsa.pem"), 118+ ])), 119+ "Check failure during BIO setup with -stream is handled correctly"); 120+ }); 121diff --git a/test/smime-certs/badrsa.pem b/test/smime-certs/badrsa.pem 122new file mode 100644 123index 0000000000..f824fc2267 124--- /dev/null 125+++ b/test/smime-certs/badrsa.pem 126@@ -0,0 +1,18 @@ 127+-----BEGIN CERTIFICATE----- 128+MIIDbTCCAlWgAwIBAgIToTV4Z0iuK08vZP20oTh//hC8BDANBgkqhkiG9w0BAQ0FADAtMSswKQYD 129+VfcDEyJTYW1wbGUgTEFNUFMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTE5MTEyMDA2NTQxOFoY 130+DzIwNTIwOTI3MDY1NDE4WjAZMRcwFQYDVQQDEw5BbGljZSBMb3ZlbGFjZTCCASIwDQYJKoZIhvcN 131+AQEBBQADggEPADCCAQoCggEBALT0iehYOBY+TZp/T5K2KNI05Hwr+E3wP6XTvyi6WWyTgBK9LCOw 132+I2juwdRrjFBmXkk7pWpjXwsA3A5GOtz0FpfgyC7OxsVcF7q4WHWZWleYXFKlQHJD73nQwXP968+A 133+/3rBX7PhO0DBbZnfitOLPgPEwjTtdg0VQQ6Wz+CRQ/YbHPKaw7aRphZO63dKvIKp4cQVtkWQHi6s 134+yTjGsgkLcLNau5LZDQUdsGV+SAo3nBdWCRYV+I65x8Kf4hCxqqmjV3d/2NKRu0BXnDe/N+iDz3X0 135+zEoj0fqXgq4SWcC0nsG1lyyXt1TL270I6ATKRGJWiQVCCpDtc0NT6vdJ45bCSxgCAwEAAaOBlzCB 136+lDAMBgNVHRMBAf8EAjAAMB4GA1UdEQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1wbGUwEwYDVR0lBAww 137+CgYIKwYBBQUHAwQwDwYDVR0PAQH/BAUDAwfAADAdBgNVHQ4EFgQUu/bMsi0dBhIcl64papAQ0yBm 138+ZnMwHwYDVR0jBBgwFoAUeF8OWnjYa+RUcD2z3ez38fL6wEcwDQYJKoZIhvcNAQENBQADggEBABbW 139+eonR6TMTckehDKNOabwaCIcekahAIL6l9tTzUX5ew6ufiAPlC6I/zQlmUaU0iSyFDG1NW14kNbFt 140+5CAokyLhMtE4ASHBIHbiOp/ZSbUBTVYJZB61ot7w1/ol5QECSs08b8zrxIncf+t2DHGuVEy/Qq1d 141+rBz8d4ay8zpqAE1tUyL5Da6ZiKUfWwZQXSI/JlbjQFzYQqTRDnzHWrg1xPeMTO1P2/cplFaseTiv 142+yk4cYwOp/W9UAWymOZXF8WcJYCIUXkdcG/nEZxr057KlScrJmFXOoh7Y+8ON4iWYYcAfiNgpUFo/ 143+j8BAwrKKaFvdlZS9k1Ypb2+UQY75mKJE9Bg= 144+-----END CERTIFICATE-----