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