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