1 /* 2 * Copyright 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 10 #include <openssl/bio.h> 11 #include "testutil.h" 12 13 static const char *filename = NULL; 14 15 /* 16 * Test that a BIO_f_readbuffer() with a BIO_new_file() behaves nicely if 17 * BIO_gets() and BIO_read_ex() are both called. 18 * Since the BIO_gets() calls buffer the reads, the BIO_read_ex() should 19 * still be able to read the buffered data if we seek back to the start. 20 * 21 * The following cases are tested using tstid: 22 * 0 : Just use BIO_read_ex(). 23 * 1 : Try a few reads using BIO_gets() before using BIO_read_ex() 24 * 2 : Read the entire file using BIO_gets() before using BIO_read_ex(). 25 */ 26 static int test_readbuffer_file_bio(int tstid) 27 { 28 int ret = 0, len, partial; 29 BIO *in = NULL, *in_bio = NULL, *readbuf_bio = NULL; 30 char buf[255]; 31 char expected[4096]; 32 size_t readbytes = 0, bytes = 0, count = 0; 33 34 /* Open a file BIO and read all the data */ 35 if (!TEST_ptr(in = BIO_new_file(filename, "r")) 36 || !TEST_int_eq(BIO_read_ex(in, expected, sizeof(expected), 37 &readbytes), 1) 38 || !TEST_int_lt(readbytes, sizeof(expected))) 39 goto err; 40 BIO_free(in); 41 in = NULL; 42 43 /* Create a new file bio that sits under a readbuffer BIO */ 44 if (!TEST_ptr(readbuf_bio = BIO_new(BIO_f_readbuffer())) 45 || !TEST_ptr(in_bio = BIO_new_file(filename, "r"))) 46 goto err; 47 48 in_bio = BIO_push(readbuf_bio, in_bio); 49 readbuf_bio = NULL; 50 51 if (!TEST_int_eq(BIO_tell(in_bio), 0)) 52 goto err; 53 54 if (tstid != 0) { 55 partial = 4; 56 while (!BIO_eof(in_bio)) { 57 len = BIO_gets(in_bio, buf, sizeof(buf)); 58 if (len == 0) { 59 if (!TEST_true(BIO_eof(in_bio))) 60 goto err; 61 } else { 62 if (!TEST_int_gt(len, 0) 63 || !TEST_int_le(len, (int)sizeof(buf) - 1)) 64 goto err; 65 if (!TEST_true(buf[len] == 0)) 66 goto err; 67 if (len > 1 68 && !BIO_eof(in_bio) 69 && len != ((int)sizeof(buf) - 1) 70 && !TEST_true(buf[len - 1] == '\n')) 71 goto err; 72 } 73 if (tstid == 1 && --partial == 0) 74 break; 75 } 76 } 77 if (!TEST_int_eq(BIO_seek(in_bio, 0), 1)) 78 goto err; 79 80 len = 8; /* Do a small partial read to start with */ 81 while (!BIO_eof(in_bio)) { 82 if (!TEST_int_eq(BIO_read_ex(in_bio, buf, len, &bytes), 1)) 83 break; 84 if (!TEST_mem_eq(buf, bytes, expected + count, bytes)) 85 goto err; 86 count += bytes; 87 len = sizeof(buf); /* fill the buffer on subsequent reads */ 88 } 89 if (!TEST_int_eq(count, readbytes)) 90 goto err; 91 ret = 1; 92 err: 93 BIO_free(in); 94 BIO_free_all(in_bio); 95 BIO_free(readbuf_bio); 96 return ret; 97 } 98 99 typedef enum OPTION_choice { 100 OPT_ERR = -1, 101 OPT_EOF = 0, 102 OPT_TEST_ENUM 103 } OPTION_CHOICE; 104 105 const OPTIONS *test_get_options(void) 106 { 107 static const OPTIONS test_options[] = { 108 OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("file\n"), 109 { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" }, 110 { NULL } 111 }; 112 return test_options; 113 } 114 115 int setup_tests(void) 116 { 117 OPTION_CHOICE o; 118 119 while ((o = opt_next()) != OPT_EOF) { 120 switch (o) { 121 case OPT_TEST_CASES: 122 break; 123 default: 124 return 0; 125 } 126 } 127 filename = test_get_argument(0); 128 129 ADD_ALL_TESTS(test_readbuffer_file_bio, 3); 130 return 1; 131 } 132