mirror of https://github.com/openssl/openssl.git
				
				
				
			
		
			
				
	
	
		
			132 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved.
 | |
|  *
 | |
|  * Licensed under the Apache License 2.0 (the "License").  You may not use
 | |
|  * this file except in compliance with the License.  You can obtain a copy
 | |
|  * in the file LICENSE in the source distribution or at
 | |
|  * https://www.openssl.org/source/license.html
 | |
|  */
 | |
| 
 | |
| #include <openssl/bio.h>
 | |
| #include "testutil.h"
 | |
| 
 | |
| static const char *filename = NULL;
 | |
| 
 | |
| /*
 | |
|  * Test that a BIO_f_readbuffer() with a BIO_new_file() behaves nicely if
 | |
|  * BIO_gets() and BIO_read_ex() are both called.
 | |
|  * Since the BIO_gets() calls buffer the reads, the BIO_read_ex() should
 | |
|  * still be able to read the buffered data if we seek back to the start.
 | |
|  *
 | |
|  * The following cases are tested using tstid:
 | |
|  * 0 : Just use BIO_read_ex().
 | |
|  * 1 : Try a few reads using BIO_gets() before using BIO_read_ex()
 | |
|  * 2 : Read the entire file using BIO_gets() before using BIO_read_ex().
 | |
|  */
 | |
| static int test_readbuffer_file_bio(int tstid)
 | |
| {
 | |
|     int ret = 0, len, partial;
 | |
|     BIO *in = NULL, *in_bio = NULL, *readbuf_bio = NULL;
 | |
|     char buf[255];
 | |
|     char expected[4096];
 | |
|     size_t readbytes = 0, bytes = 0, count = 0;
 | |
| 
 | |
|     /* Open a file BIO and read all the data */
 | |
|     if (!TEST_ptr(in = BIO_new_file(filename, "r"))
 | |
|         || !TEST_int_eq(BIO_read_ex(in, expected, sizeof(expected),
 | |
|                                     &readbytes), 1)
 | |
|         || !TEST_size_t_lt(readbytes, sizeof(expected)))
 | |
|         goto err;
 | |
|     BIO_free(in);
 | |
|     in = NULL;
 | |
| 
 | |
|     /* Create a new file bio that sits under a readbuffer BIO */
 | |
|     if (!TEST_ptr(readbuf_bio = BIO_new(BIO_f_readbuffer()))
 | |
|         || !TEST_ptr(in_bio = BIO_new_file(filename, "r")))
 | |
|         goto err;
 | |
| 
 | |
|     in_bio = BIO_push(readbuf_bio, in_bio);
 | |
|     readbuf_bio = NULL;
 | |
| 
 | |
|     if (!TEST_int_eq(BIO_tell(in_bio), 0))
 | |
|         goto err;
 | |
| 
 | |
|     if (tstid != 0) {
 | |
|         partial = 4;
 | |
|         while (!BIO_eof(in_bio)) {
 | |
|             len = BIO_gets(in_bio, buf, sizeof(buf));
 | |
|             if (len == 0) {
 | |
|                 if (!TEST_true(BIO_eof(in_bio)))
 | |
|                     goto err;
 | |
|             } else {
 | |
|                 if (!TEST_int_gt(len, 0)
 | |
|                     || !TEST_int_le(len, (int)sizeof(buf) - 1))
 | |
|                     goto err;
 | |
|                 if (!TEST_true(buf[len] == 0))
 | |
|                     goto err;
 | |
|                 if (len > 1
 | |
|                     && !BIO_eof(in_bio)
 | |
|                     && len != ((int)sizeof(buf) - 1)
 | |
|                     && !TEST_true(buf[len - 1] == '\n'))
 | |
|                     goto err;
 | |
|             }
 | |
|             if (tstid == 1 && --partial == 0)
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
|     if (!TEST_int_eq(BIO_seek(in_bio, 0), 1))
 | |
|         goto err;
 | |
| 
 | |
|     len = 8; /* Do a small partial read to start with */
 | |
|     while (!BIO_eof(in_bio)) {
 | |
|         if (!TEST_int_eq(BIO_read_ex(in_bio, buf, len, &bytes), 1))
 | |
|             break;
 | |
|         if (!TEST_mem_eq(buf, bytes, expected + count, bytes))
 | |
|             goto err;
 | |
|         count += bytes;
 | |
|         len = sizeof(buf); /* fill the buffer on subsequent reads */
 | |
|     }
 | |
|     if (!TEST_size_t_eq(count, readbytes))
 | |
|         goto err;
 | |
|     ret = 1;
 | |
| err:
 | |
|     BIO_free(in);
 | |
|     BIO_free_all(in_bio);
 | |
|     BIO_free(readbuf_bio);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| typedef enum OPTION_choice {
 | |
|     OPT_ERR = -1,
 | |
|     OPT_EOF = 0,
 | |
|     OPT_TEST_ENUM
 | |
| } OPTION_CHOICE;
 | |
| 
 | |
| const OPTIONS *test_get_options(void)
 | |
| {
 | |
|     static const OPTIONS test_options[] = {
 | |
|         OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("file\n"),
 | |
|         { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" },
 | |
|         { NULL }
 | |
|     };
 | |
|     return test_options;
 | |
| }
 | |
| 
 | |
| int setup_tests(void)
 | |
| {
 | |
|     OPTION_CHOICE o;
 | |
| 
 | |
|     while ((o = opt_next()) != OPT_EOF) {
 | |
|         switch (o) {
 | |
|         case OPT_TEST_CASES:
 | |
|             break;
 | |
|         default:
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
|     filename = test_get_argument(0);
 | |
| 
 | |
|     ADD_ALL_TESTS(test_readbuffer_file_bio, 3);
 | |
|     return 1;
 | |
| }
 |