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