1 1.1 christos /* 2 1.1 christos * Copyright (c) Meta Platforms, Inc. and affiliates. 3 1.1 christos * All rights reserved. 4 1.1 christos * 5 1.1 christos * This source code is licensed under both the BSD-style license (found in the 6 1.1 christos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7 1.1 christos * in the COPYING file in the root directory of this source tree). 8 1.1 christos * You may select, at your option, one of the above-listed licenses. 9 1.1 christos */ 10 1.1 christos 11 1.1 christos #include "fuzz_helpers.h" 12 1.1 christos #include "fuzz_data_producer.h" 13 1.1 christos 14 1.1 christos struct FUZZ_dataProducer_s{ 15 1.1 christos const uint8_t *data; 16 1.1 christos size_t size; 17 1.1 christos }; 18 1.1 christos 19 1.1 christos FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) { 20 1.1 christos FUZZ_dataProducer_t *producer = FUZZ_malloc(sizeof(FUZZ_dataProducer_t)); 21 1.1 christos 22 1.1 christos producer->data = data; 23 1.1 christos producer->size = size; 24 1.1 christos return producer; 25 1.1 christos } 26 1.1 christos 27 1.1 christos void FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer) { free(producer); } 28 1.1 christos 29 1.1 christos uint32_t FUZZ_dataProducer_uint32Range(FUZZ_dataProducer_t *producer, uint32_t min, 30 1.1 christos uint32_t max) { 31 1.1 christos uint32_t range = max - min; 32 1.1 christos uint32_t rolling = range; 33 1.1 christos uint32_t result = 0; 34 1.1 christos 35 1.1 christos FUZZ_ASSERT(min <= max); 36 1.1 christos 37 1.1 christos while (rolling > 0 && producer->size > 0) { 38 1.1 christos uint8_t next = *(producer->data + producer->size - 1); 39 1.1 christos producer->size -= 1; 40 1.1 christos result = (result << 8) | next; 41 1.1 christos rolling >>= 8; 42 1.1 christos } 43 1.1 christos 44 1.1 christos if (range == 0xffffffff) { 45 1.1 christos return result; 46 1.1 christos } 47 1.1 christos 48 1.1 christos return min + result % (range + 1); 49 1.1 christos } 50 1.1 christos 51 1.1 christos uint32_t FUZZ_dataProducer_uint32(FUZZ_dataProducer_t *producer) { 52 1.1 christos return FUZZ_dataProducer_uint32Range(producer, 0, 0xffffffff); 53 1.1 christos } 54 1.1 christos 55 1.1 christos int32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer, 56 1.1 christos int32_t min, int32_t max) 57 1.1 christos { 58 1.1 christos FUZZ_ASSERT(min <= max); 59 1.1 christos 60 1.1 christos if (min < 0) 61 1.1 christos return (int)FUZZ_dataProducer_uint32Range(producer, 0, max - min) + min; 62 1.1 christos 63 1.1 christos return FUZZ_dataProducer_uint32Range(producer, min, max); 64 1.1 christos } 65 1.1 christos 66 1.1 christos size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer){ 67 1.1 christos return producer->size; 68 1.1 christos } 69 1.1 christos 70 1.1 christos void FUZZ_dataProducer_rollBack(FUZZ_dataProducer_t *producer, size_t remainingBytes) 71 1.1 christos { 72 1.1 christos FUZZ_ASSERT(remainingBytes >= producer->size); 73 1.1 christos producer->size = remainingBytes; 74 1.1 christos } 75 1.1 christos 76 1.1 christos int FUZZ_dataProducer_empty(FUZZ_dataProducer_t *producer) { 77 1.1 christos return producer->size == 0; 78 1.1 christos } 79 1.1 christos 80 1.1 christos size_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize) 81 1.1 christos { 82 1.1 christos const size_t effectiveNewSize = newSize > producer->size ? producer->size : newSize; 83 1.1 christos 84 1.1 christos size_t remaining = producer->size - effectiveNewSize; 85 1.1 christos producer->data = producer->data + remaining; 86 1.1 christos producer->size = effectiveNewSize; 87 1.1 christos return remaining; 88 1.1 christos } 89 1.1 christos 90 1.1 christos size_t FUZZ_dataProducer_reserveDataPrefix(FUZZ_dataProducer_t *producer) 91 1.1 christos { 92 1.1 christos size_t producerSliceSize = FUZZ_dataProducer_uint32Range( 93 1.1 christos producer, 0, producer->size); 94 1.1 christos return FUZZ_dataProducer_contract(producer, producerSliceSize); 95 1.1 christos } 96