Path: blob/main/contrib/libarchive/test_utils/test_utils.c
39586 views
/*1* Copyright (c) 2003-2012 Tim Kientzle2* Copyright (c) 2012 Andres Mejia3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.17* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include "test_utils.h"2728#include <errno.h>29#include <stdlib.h>30#include <stdio.h>31#include <string.h>32#include <assert.h>3334static inline uint64_t35xorshift64(uint64_t *state)36{37uint64_t x = *state;38x ^= x << 13;39x ^= x >> 7;40x ^= x << 17;41*state = x;42return (x);43}4445/*46* Fill a buffer with reproducible pseudo-random data using a simple xorshift47* algorithm. Originally, most tests filled buffers with a loop that calls48* rand() once for each byte. However, this initialization can be extremely49* slow when running on emulated platforms such as QEMU where 16M calls to50* rand() take a long time: Before the test_write_format_7zip_large_copy test51* took ~22 seconds, whereas using a xorshift random number generator (that can52* be inlined) reduces it to ~17 seconds on QEMU RISC-V.53*/54static void55fill_with_pseudorandom_data_seed(uint64_t seed, void *buffer, size_t size)56{57uint64_t *aligned_buffer;58size_t num_values;59size_t i;60size_t unaligned_suffix;61size_t unaligned_prefix = 0;62/*63* To avoid unaligned stores we only fill the aligned part of the buffer64* with pseudo-random data and fill the unaligned prefix with 0xab and65* the suffix with 0xcd.66*/67if ((uintptr_t)buffer % sizeof(uint64_t)) {68unaligned_prefix =69sizeof(uint64_t) - (uintptr_t)buffer % sizeof(uint64_t);70aligned_buffer =71(uint64_t *)((char *)buffer + unaligned_prefix);72memset(buffer, 0xab, unaligned_prefix);73} else {74aligned_buffer = (uint64_t *)buffer;75}76assert((uintptr_t)aligned_buffer % sizeof(uint64_t) == 0);77num_values = (size - unaligned_prefix) / sizeof(uint64_t);78unaligned_suffix =79size - unaligned_prefix - num_values * sizeof(uint64_t);80for (i = 0; i < num_values; i++) {81aligned_buffer[i] = xorshift64(&seed);82}83if (unaligned_suffix) {84memset((char *)buffer + size - unaligned_suffix, 0xcd,85unaligned_suffix);86}87}8889void90fill_with_pseudorandom_data(void *buffer, size_t size)91{92uint64_t seed;93const char* seed_str;94/*95* Check if a seed has been specified in the environment, otherwise fall96* back to using rand() as a seed.97*/98if ((seed_str = getenv("TEST_RANDOM_SEED")) != NULL) {99errno = 0;100seed = strtoull(seed_str, NULL, 10);101if (errno != 0) {102fprintf(stderr, "strtoull(%s) failed: %s", seed_str,103strerror(errno));104seed = rand();105}106} else {107seed = rand();108}109fill_with_pseudorandom_data_seed(seed, buffer, size);110}111112unsigned long113bitcrc32(unsigned long c, const void *_p, size_t s)114{115/* This is a drop-in replacement for crc32() from zlib.116* Libarchive should be able to correctly read archives (including117* correct CRCs) even when zlib is unavailable, and this function118* helps us verify that. Yes, this is very, very slow and unsuitable119* for production use, but it's obviously correct, compact, and120* works well enough for this particular usage. Libarchive121* internally uses a much more efficient implementation if zlib is122* unavailable. */123const unsigned char *p = _p;124char bitctr;125126if (p == NULL)127return (0);128129for (; s > 0; --s) {130c ^= *p++;131for (bitctr = 8; bitctr > 0; --bitctr) {132if (c & 1) c = (c >> 1);133else c = (c >> 1) ^ 0xedb88320;134c ^= 0x80000000;135}136}137return (c);138}139140/* Read little-endian integers */141unsigned short142i2le(const void* p_)143{144const unsigned char *p = p_;145return (p[0] | (p[1] << 8));146}147unsigned int148i4le(const void* p_)149{150const char *p = p_;151return (i2le(p) | (i2le(p + 2) << 16));152}153unsigned long long154i8le(const void* p_)155{156const char *p = p_;157return (i4le(p) | ((unsigned long long)i4le(p + 4) << 32));158}159160161