@@ -49,12 +49,19 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
49
49
static int ndef_suffix_free (BIO * b , unsigned char * * pbuf , int * plen ,
50
50
void * parg );
51
51
52
+ /*
53
+ * On success, the returned BIO owns the input BIO as part of its BIO chain.
54
+ * On failure, NULL is returned and the input BIO is owned by the caller.
55
+ *
56
+ * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream()
57
+ */
52
58
BIO * BIO_new_NDEF (BIO * out , ASN1_VALUE * val , const ASN1_ITEM * it )
53
59
{
54
60
NDEF_SUPPORT * ndef_aux = NULL ;
55
61
BIO * asn_bio = NULL ;
56
62
const ASN1_AUX * aux = it -> funcs ;
57
63
ASN1_STREAM_ARG sarg ;
64
+ BIO * pop_bio = NULL ;
58
65
59
66
if (!aux || !aux -> asn1_cb ) {
60
67
ASN1err (ASN1_F_BIO_NEW_NDEF , ASN1_R_STREAMING_NOT_SUPPORTED );
@@ -69,33 +76,51 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
69
76
out = BIO_push (asn_bio , out );
70
77
if (out == NULL )
71
78
goto err ;
79
+ pop_bio = asn_bio ;
72
80
73
- BIO_asn1_set_prefix (asn_bio , ndef_prefix , ndef_prefix_free );
74
- BIO_asn1_set_suffix (asn_bio , ndef_suffix , ndef_suffix_free );
81
+ if (BIO_asn1_set_prefix (asn_bio , ndef_prefix , ndef_prefix_free ) <= 0
82
+ || BIO_asn1_set_suffix (asn_bio , ndef_suffix , ndef_suffix_free ) <= 0
83
+ || BIO_ctrl (asn_bio , BIO_C_SET_EX_ARG , 0 , ndef_aux ) <= 0 )
84
+ goto err ;
75
85
76
86
/*
77
- * Now let callback prepends any digest, cipher etc BIOs ASN1 structure
78
- * needs.
87
+ * Now let the callback prepend any digest, cipher, etc., that the BIO's
88
+ * ASN1 structure needs.
79
89
*/
80
90
81
91
sarg .out = out ;
82
92
sarg .ndef_bio = NULL ;
83
93
sarg .boundary = NULL ;
84
94
85
- if (aux -> asn1_cb (ASN1_OP_STREAM_PRE , & val , it , & sarg ) <= 0 )
95
+ /*
96
+ * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the
97
+ * middle of some partially built, but not returned BIO chain.
98
+ */
99
+ if (aux -> asn1_cb (ASN1_OP_STREAM_PRE , & val , it , & sarg ) <= 0 ) {
100
+ /*
101
+ * ndef_aux is now owned by asn_bio so we must not free it in the err
102
+ * clean up block
103
+ */
104
+ ndef_aux = NULL ;
86
105
goto err ;
106
+ }
107
+
108
+ /*
109
+ * We must not fail now because the callback has prepended additional
110
+ * BIOs to the chain
111
+ */
87
112
88
113
ndef_aux -> val = val ;
89
114
ndef_aux -> it = it ;
90
115
ndef_aux -> ndef_bio = sarg .ndef_bio ;
91
116
ndef_aux -> boundary = sarg .boundary ;
92
117
ndef_aux -> out = out ;
93
118
94
- BIO_ctrl (asn_bio , BIO_C_SET_EX_ARG , 0 , ndef_aux );
95
-
96
119
return sarg .ndef_bio ;
97
120
98
121
err :
122
+ /* BIO_pop() is NULL safe */
123
+ (void )BIO_pop (pop_bio );
99
124
BIO_free (asn_bio );
100
125
OPENSSL_free (ndef_aux );
101
126
return NULL ;
0 commit comments