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