Home | History | Annotate | Line # | Download | only in test
      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