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