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 | }
|
---|