xref: /netbsd-src/crypto/external/bsd/openssl/dist/test/bio_memleak_test.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /*
2  * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 #include <stdio.h>
10 #include <string.h>
11 #include <openssl/buffer.h>
12 #include <openssl/bio.h>
13 #include <openssl/pkcs7.h>
14 #include <openssl/obj_mac.h>
15 
16 #include "testutil.h"
17 
18 static int test_bio_memleak(void)
19 {
20     int ok = 0;
21     BIO *bio;
22     BUF_MEM bufmem;
23     static const char str[] = "BIO test\n";
24     char buf[100];
25 
26     bio = BIO_new(BIO_s_mem());
27     if (!TEST_ptr(bio))
28         goto finish;
29     bufmem.length = sizeof(str);
30     bufmem.data = (char *) str;
31     bufmem.max = bufmem.length;
32     BIO_set_mem_buf(bio, &bufmem, BIO_NOCLOSE);
33     BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
34     if (!TEST_int_eq(BIO_read(bio, buf, sizeof(buf)), sizeof(str)))
35         goto finish;
36     if (!TEST_mem_eq(buf, sizeof(str), str, sizeof(str)))
37         goto finish;
38     ok = 1;
39 
40  finish:
41     BIO_free(bio);
42     return ok;
43 }
44 
45 static int test_bio_get_mem(void)
46 {
47     int ok = 0;
48     BIO *bio = NULL;
49     BUF_MEM *bufmem = NULL;
50 
51     bio = BIO_new(BIO_s_mem());
52     if (!TEST_ptr(bio))
53         goto finish;
54     if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
55         goto finish;
56     BIO_get_mem_ptr(bio, &bufmem);
57     if (!TEST_ptr(bufmem))
58         goto finish;
59     if (!TEST_int_gt(BIO_set_close(bio, BIO_NOCLOSE), 0))
60         goto finish;
61     BIO_free(bio);
62     bio = NULL;
63     if (!TEST_mem_eq(bufmem->data, bufmem->length, "Hello World\n", 12))
64         goto finish;
65     ok = 1;
66 
67  finish:
68     BIO_free(bio);
69     BUF_MEM_free(bufmem);
70     return ok;
71 }
72 
73 static int test_bio_new_mem_buf(void)
74 {
75     int ok = 0;
76     BIO *bio;
77     BUF_MEM *bufmem;
78     char data[16];
79 
80     bio = BIO_new_mem_buf("Hello World\n", 12);
81     if (!TEST_ptr(bio))
82         goto finish;
83     if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
84         goto finish;
85     if (!TEST_mem_eq(data, 5, "Hello", 5))
86         goto finish;
87     if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
88         goto finish;
89     if (!TEST_int_lt(BIO_write(bio, "test", 4), 0))
90         goto finish;
91     if (!TEST_int_eq(BIO_read(bio, data, 16), 7))
92         goto finish;
93     if (!TEST_mem_eq(data, 7, " World\n", 7))
94         goto finish;
95     if (!TEST_int_gt(BIO_reset(bio), 0))
96         goto finish;
97     if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
98         goto finish;
99     if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
100         goto finish;
101     ok = 1;
102 
103  finish:
104     BIO_free(bio);
105     return ok;
106 }
107 
108 static int test_bio_rdonly_mem_buf(void)
109 {
110     int ok = 0;
111     BIO *bio, *bio2 = NULL;
112     BUF_MEM *bufmem;
113     char data[16];
114 
115     bio = BIO_new_mem_buf("Hello World\n", 12);
116     if (!TEST_ptr(bio))
117         goto finish;
118     if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
119         goto finish;
120     if (!TEST_mem_eq(data, 5, "Hello", 5))
121         goto finish;
122     if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
123         goto finish;
124     (void)BIO_set_close(bio, BIO_NOCLOSE);
125 
126     bio2 = BIO_new(BIO_s_mem());
127     if (!TEST_ptr(bio2))
128         goto finish;
129     BIO_set_mem_buf(bio2, bufmem, BIO_CLOSE);
130     BIO_set_flags(bio2, BIO_FLAGS_MEM_RDONLY);
131 
132     if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
133         goto finish;
134     if (!TEST_mem_eq(data, 7, " World\n", 7))
135         goto finish;
136     if (!TEST_int_gt(BIO_reset(bio2), 0))
137         goto finish;
138     if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
139         goto finish;
140     if (!TEST_mem_eq(data, 7, " World\n", 7))
141         goto finish;
142     ok = 1;
143 
144  finish:
145     BIO_free(bio);
146     BIO_free(bio2);
147     return ok;
148 }
149 
150 static int test_bio_rdwr_rdonly(void)
151 {
152     int ok = 0;
153     BIO *bio = NULL;
154     char data[16];
155 
156     bio = BIO_new(BIO_s_mem());
157     if (!TEST_ptr(bio))
158         goto finish;
159     if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
160         goto finish;
161 
162     BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
163     if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
164         goto finish;
165     if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
166         goto finish;
167     if (!TEST_int_gt(BIO_reset(bio), 0))
168         goto finish;
169 
170     BIO_clear_flags(bio, BIO_FLAGS_MEM_RDONLY);
171     if (!TEST_int_eq(BIO_puts(bio, "Hi!\n"), 4))
172         goto finish;
173     if (!TEST_int_eq(BIO_read(bio, data, 16), 16))
174         goto finish;
175 
176     if (!TEST_mem_eq(data, 16, "Hello World\nHi!\n", 16))
177         goto finish;
178 
179     ok = 1;
180 
181  finish:
182     BIO_free(bio);
183     return ok;
184 }
185 
186 static int test_bio_nonclear_rst(void)
187 {
188     int ok = 0;
189     BIO *bio = NULL;
190     char data[16];
191 
192     bio = BIO_new(BIO_s_mem());
193     if (!TEST_ptr(bio))
194         goto finish;
195     if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
196         goto finish;
197 
198     BIO_set_flags(bio, BIO_FLAGS_NONCLEAR_RST);
199 
200     if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
201         goto finish;
202     if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
203         goto finish;
204     if (!TEST_int_gt(BIO_reset(bio), 0))
205         goto finish;
206 
207     if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
208         goto finish;
209     if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
210         goto finish;
211 
212     BIO_clear_flags(bio, BIO_FLAGS_NONCLEAR_RST);
213     if (!TEST_int_gt(BIO_reset(bio), 0))
214         goto finish;
215 
216     if (!TEST_int_lt(BIO_read(bio, data, 16), 1))
217         goto finish;
218 
219     ok = 1;
220 
221  finish:
222     BIO_free(bio);
223     return ok;
224 }
225 
226 static int error_callback_fired;
227 static long BIO_error_callback(BIO *bio, int cmd, const char *argp,
228                                size_t len, int argi,
229                                long argl, int ret, size_t *processed)
230 {
231     if ((cmd & (BIO_CB_READ | BIO_CB_RETURN)) != 0) {
232         error_callback_fired = 1;
233         ret = 0;  /* fail for read operations to simulate error in input BIO */
234     }
235     return ret;
236 }
237 
238 /* Checks i2d_ASN1_bio_stream() is freeing all memory when input BIO ends unexpectedly. */
239 static int test_bio_i2d_ASN1_mime(void)
240 {
241     int ok = 0;
242     BIO *bio = NULL, *out = NULL;
243     BUF_MEM bufmem;
244     static const char str[] = "BIO mime test\n";
245     PKCS7 *p7 = NULL;
246 
247     if (!TEST_ptr(bio = BIO_new(BIO_s_mem())))
248         goto finish;
249 
250     bufmem.length = sizeof(str);
251     bufmem.data = (char *) str;
252     bufmem.max = bufmem.length;
253     BIO_set_mem_buf(bio, &bufmem, BIO_NOCLOSE);
254     BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
255     BIO_set_callback_ex(bio, BIO_error_callback);
256 
257     if (!TEST_ptr(out = BIO_new(BIO_s_mem())))
258         goto finish;
259     if (!TEST_ptr(p7 = PKCS7_new()))
260         goto finish;
261     if (!TEST_true(PKCS7_set_type(p7, NID_pkcs7_data)))
262         goto finish;
263 
264     error_callback_fired = 0;
265 
266     /*
267      * The call succeeds even if the input stream ends unexpectedly as
268      * there is no handling for this case in SMIME_crlf_copy().
269      */
270     if (!TEST_true(i2d_ASN1_bio_stream(out, (ASN1_VALUE*) p7, bio,
271                                        SMIME_STREAM | SMIME_BINARY,
272                                        ASN1_ITEM_rptr(PKCS7))))
273         goto finish;
274 
275     if (!TEST_int_eq(error_callback_fired, 1))
276         goto finish;
277 
278     ok = 1;
279 
280  finish:
281     BIO_free(bio);
282     BIO_free(out);
283     PKCS7_free(p7);
284     return ok;
285 }
286 
287 int global_init(void)
288 {
289     CRYPTO_set_mem_debug(1);
290     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
291     return 1;
292 }
293 
294 int setup_tests(void)
295 {
296     ADD_TEST(test_bio_memleak);
297     ADD_TEST(test_bio_get_mem);
298     ADD_TEST(test_bio_new_mem_buf);
299     ADD_TEST(test_bio_rdonly_mem_buf);
300     ADD_TEST(test_bio_rdwr_rdonly);
301     ADD_TEST(test_bio_nonclear_rst);
302     ADD_TEST(test_bio_i2d_ASN1_mime);
303     return 1;
304 }
305