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