blob: 610f8febc7501ca06d15b281fec220f18c2c3f1f [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
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
18static 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
45static 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
73static 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
108static 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
150static 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
186static 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
226static int error_callback_fired;
227static 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. */
239static 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
287int global_init(void)
288{
289 CRYPTO_set_mem_debug(1);
290 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
291 return 1;
292}
293
294int 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}