xref: /freebsd/crypto/openssl/test/bio_readbuffer_test.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
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  */
test_readbuffer_file_bio(int tstid)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),
38             1)
39         || !TEST_int_lt(readbytes, sizeof(expected)))
40         goto err;
41     BIO_free(in);
42     in = NULL;
43 
44     /* Create a new file bio that sits under a readbuffer BIO */
45     if (!TEST_ptr(readbuf_bio = BIO_new(BIO_f_readbuffer()))
46         || !TEST_ptr(in_bio = BIO_new_file(filename, "r")))
47         goto err;
48 
49     in_bio = BIO_push(readbuf_bio, in_bio);
50     readbuf_bio = NULL;
51 
52     if (!TEST_int_eq(BIO_tell(in_bio), 0))
53         goto err;
54 
55     if (tstid != 0) {
56         partial = 4;
57         while (!BIO_eof(in_bio)) {
58             len = BIO_gets(in_bio, buf, sizeof(buf));
59             if (len == 0) {
60                 if (!TEST_true(BIO_eof(in_bio)))
61                     goto err;
62             } else {
63                 if (!TEST_int_gt(len, 0)
64                     || !TEST_int_le(len, (int)sizeof(buf) - 1))
65                     goto err;
66                 if (!TEST_true(buf[len] == 0))
67                     goto err;
68                 if (len > 1
69                     && !BIO_eof(in_bio)
70                     && len != ((int)sizeof(buf) - 1)
71                     && !TEST_true(buf[len - 1] == '\n'))
72                     goto err;
73             }
74             if (tstid == 1 && --partial == 0)
75                 break;
76         }
77     }
78     if (!TEST_int_eq(BIO_seek(in_bio, 0), 1))
79         goto err;
80 
81     len = 8; /* Do a small partial read to start with */
82     while (!BIO_eof(in_bio)) {
83         if (!TEST_int_eq(BIO_read_ex(in_bio, buf, len, &bytes), 1))
84             break;
85         if (!TEST_mem_eq(buf, bytes, expected + count, bytes))
86             goto err;
87         count += bytes;
88         len = sizeof(buf); /* fill the buffer on subsequent reads */
89     }
90     if (!TEST_int_eq(count, readbytes))
91         goto err;
92     ret = 1;
93 err:
94     BIO_free(in);
95     BIO_free_all(in_bio);
96     BIO_free(readbuf_bio);
97     return ret;
98 }
99 
100 typedef enum OPTION_choice {
101     OPT_ERR = -1,
102     OPT_EOF = 0,
103     OPT_TEST_ENUM
104 } OPTION_CHOICE;
105 
test_get_options(void)106 const OPTIONS *test_get_options(void)
107 {
108     static const OPTIONS test_options[] = {
109         OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("file\n"),
110         { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" },
111         { NULL }
112     };
113     return test_options;
114 }
115 
setup_tests(void)116 int setup_tests(void)
117 {
118     OPTION_CHOICE o;
119 
120     while ((o = opt_next()) != OPT_EOF) {
121         switch (o) {
122         case OPT_TEST_CASES:
123             break;
124         default:
125             return 0;
126         }
127     }
128     filename = test_get_argument(0);
129 
130     ADD_ALL_TESTS(test_readbuffer_file_bio, 3);
131     return 1;
132 }
133