xref: /netbsd-src/external/bsd/zstd/dist/tests/fuzz/fuzz_data_producer.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
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