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