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