1 /* 2 * Copyright (c) 2003-2012 Tim Kientzle 3 * Copyright (c) 2012 Andres Mejia 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "test_utils.h" 28 29 #include <errno.h> 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <assert.h> 34 35 static inline uint64_t 36 xorshift64(uint64_t *state) 37 { 38 uint64_t x = *state; 39 x ^= x << 13; 40 x ^= x >> 7; 41 x ^= x << 17; 42 *state = x; 43 return (x); 44 } 45 46 /* 47 * Fill a buffer with reproducible pseudo-random data using a simple xorshift 48 * algorithm. Originally, most tests filled buffers with a loop that calls 49 * rand() once for each byte. However, this initialization can be extremely 50 * slow when running on emulated platforms such as QEMU where 16M calls to 51 * rand() take a long time: Before the test_write_format_7zip_large_copy test 52 * took ~22 seconds, whereas using a xorshift random number generator (that can 53 * be inlined) reduces it to ~17 seconds on QEMU RISC-V. 54 */ 55 static void 56 fill_with_pseudorandom_data_seed(uint64_t seed, void *buffer, size_t size) 57 { 58 uint64_t *aligned_buffer; 59 size_t num_values; 60 size_t i; 61 size_t unaligned_suffix; 62 size_t unaligned_prefix = 0; 63 /* 64 * To avoid unaligned stores we only fill the aligned part of the buffer 65 * with pseudo-random data and fill the unaligned prefix with 0xab and 66 * the suffix with 0xcd. 67 */ 68 if ((uintptr_t)buffer % sizeof(uint64_t)) { 69 unaligned_prefix = 70 sizeof(uint64_t) - (uintptr_t)buffer % sizeof(uint64_t); 71 aligned_buffer = 72 (uint64_t *)((char *)buffer + unaligned_prefix); 73 memset(buffer, 0xab, unaligned_prefix); 74 } else { 75 aligned_buffer = (uint64_t *)buffer; 76 } 77 assert((uintptr_t)aligned_buffer % sizeof(uint64_t) == 0); 78 num_values = (size - unaligned_prefix) / sizeof(uint64_t); 79 unaligned_suffix = 80 size - unaligned_prefix - num_values * sizeof(uint64_t); 81 for (i = 0; i < num_values; i++) { 82 aligned_buffer[i] = xorshift64(&seed); 83 } 84 if (unaligned_suffix) { 85 memset((char *)buffer + size - unaligned_suffix, 0xcd, 86 unaligned_suffix); 87 } 88 } 89 90 void 91 fill_with_pseudorandom_data(void *buffer, size_t size) 92 { 93 uint64_t seed; 94 const char* seed_str; 95 /* 96 * Check if a seed has been specified in the environment, otherwise fall 97 * back to using rand() as a seed. 98 */ 99 if ((seed_str = getenv("TEST_RANDOM_SEED")) != NULL) { 100 errno = 0; 101 seed = strtoull(seed_str, NULL, 10); 102 if (errno != 0) { 103 fprintf(stderr, "strtoull(%s) failed: %s", seed_str, 104 strerror(errno)); 105 seed = rand(); 106 } 107 } else { 108 seed = rand(); 109 } 110 fill_with_pseudorandom_data_seed(seed, buffer, size); 111 } 112 113 unsigned long 114 bitcrc32(unsigned long c, const void *_p, size_t s) 115 { 116 /* This is a drop-in replacement for crc32() from zlib. 117 * Libarchive should be able to correctly read archives (including 118 * correct CRCs) even when zlib is unavailable, and this function 119 * helps us verify that. Yes, this is very, very slow and unsuitable 120 * for production use, but it's obviously correct, compact, and 121 * works well enough for this particular usage. Libarchive 122 * internally uses a much more efficient implementation if zlib is 123 * unavailable. */ 124 const unsigned char *p = _p; 125 char bitctr; 126 127 if (p == NULL) 128 return (0); 129 130 for (; s > 0; --s) { 131 c ^= *p++; 132 for (bitctr = 8; bitctr > 0; --bitctr) { 133 if (c & 1) c = (c >> 1); 134 else c = (c >> 1) ^ 0xedb88320; 135 c ^= 0x80000000; 136 } 137 } 138 return (c); 139 } 140 141 /* Read little-endian integers */ 142 unsigned short 143 i2le(const void* p_) 144 { 145 const unsigned char *p = p_; 146 return (p[0] | (p[1] << 8)); 147 } 148 unsigned int 149 i4le(const void* p_) 150 { 151 const char *p = p_; 152 return (i2le(p) | (i2le(p + 2) << 16)); 153 } 154 unsigned long long 155 i8le(const void* p_) 156 { 157 const char *p = p_; 158 return (i4le(p) | ((unsigned long long)i4le(p + 4) << 32)); 159 } 160