Coverage Report

Created: 2024-07-27 06:12

/src/lzma-fuzz/common-buffer.h
Line
Count
Source (jump to first uncovered line)
1
/**
2
 *
3
 * @copyright Copyright (c) 2019 Joachim Bauch <mail@joachim-bauch.de>
4
 *
5
 * @license GNU GPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
#include <assert.h>
23
#include <stdint.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "7zTypes.h"
28
29
class OutputBuffer {
30
 public:
31
  OutputBuffer();
32
  ~OutputBuffer();
33
34
0
  ISeqOutStream *stream() { return &stream_.vt; };
35
0
  const uint8_t *data() const { return data_; }
36
0
  size_t size() const { return position_; }
37
38
 private:
39
  static const size_t kInitialSize = 128;
40
41
  typedef struct {
42
    ISeqOutStream vt;
43
    OutputBuffer *buffer;
44
  } OutputBufferStream;
45
46
  static size_t _Write(const ISeqOutStream *pp, const void *data, size_t size);
47
  size_t Write(const void *data, size_t size);
48
49
  OutputBufferStream stream_;
50
  uint8_t *data_ = nullptr;
51
  size_t size_ = 0;
52
  size_t position_ = 0;
53
};
54
55
0
OutputBuffer::OutputBuffer() {
56
0
  stream_.vt.Write = &OutputBuffer::_Write;
57
0
  stream_.buffer = this;
58
0
}
59
60
0
OutputBuffer::~OutputBuffer() {
61
0
  free(data_);
62
0
}
63
64
// static
65
size_t OutputBuffer::_Write(const ISeqOutStream *p, const void *data,
66
0
    size_t size) {
67
0
  OutputBufferStream *stream = CONTAINER_FROM_VTBL(p, OutputBufferStream, vt);
68
0
  return stream->buffer->Write(data, size);
69
0
}
70
71
0
size_t OutputBuffer::Write(const void *data, size_t size) {
72
0
  size_t available = size_ - position_;
73
0
  if (available < size) {
74
0
    if (!size_) {
75
0
      size_ = kInitialSize;
76
0
    }
77
0
    while (size_ - position_ < size) {
78
0
      size_ *= 2;
79
0
    }
80
0
    uint8_t *tmp = static_cast<uint8_t*>(malloc(size_));
81
0
    assert(tmp);
82
0
    if (data_) {
83
0
      memcpy(tmp, data_, position_);
84
0
      free(data_);
85
0
    }
86
0
    data_ = tmp;
87
0
  }
88
89
0
  memcpy(data_ + position_, data, size);
90
0
  position_ += size;
91
0
  return size;
92
0
}
93
94
class OutputByteBuffer {
95
 public:
96
  OutputByteBuffer();
97
  ~OutputByteBuffer();
98
99
0
  IByteOut *stream() { return &stream_.vt; };
100
0
  const uint8_t *data() const { return data_; }
101
0
  size_t size() const { return position_; }
102
103
 private:
104
  static const size_t kInitialSize = 128;
105
106
  typedef struct {
107
    IByteOut vt;
108
    OutputByteBuffer *buffer;
109
  } ByteOutStream;
110
111
  static void _Write(const IByteOut *pp, Byte b);
112
  void Write(Byte b);
113
114
  ByteOutStream stream_;
115
  uint8_t *data_ = nullptr;
116
  size_t size_ = 0;
117
  size_t position_ = 0;
118
};
119
120
0
OutputByteBuffer::OutputByteBuffer() {
121
0
  stream_.vt.Write = &OutputByteBuffer::_Write;
122
0
  stream_.buffer = this;
123
0
}
124
125
0
OutputByteBuffer::~OutputByteBuffer() {
126
0
  free(data_);
127
0
}
128
129
// static
130
0
void OutputByteBuffer::_Write(const IByteOut *p, Byte b) {
131
0
  ByteOutStream *stream = CONTAINER_FROM_VTBL(p, ByteOutStream, vt);
132
0
  stream->buffer->Write(b);
133
0
}
134
135
0
void OutputByteBuffer::Write(Byte b) {
136
0
  if (size_ == position_) {
137
0
    if (!size_) {
138
0
      size_ = kInitialSize;
139
0
    } else {
140
0
      size_ *= 2;
141
0
    }
142
0
    uint8_t *tmp = static_cast<uint8_t*>(malloc(size_));
143
0
    assert(tmp);
144
0
    if (data_) {
145
0
      memcpy(tmp, data_, position_);
146
0
      free(data_);
147
0
    }
148
0
    data_ = tmp;
149
0
  }
150
151
0
  data_[position_++] = b;
152
0
}
153
154
class InputBuffer {
155
 public:
156
  InputBuffer(const uint8_t *data, size_t size);
157
158
0
  ISeqInStream *stream() { return &stream_.vt; };
159
160
 private:
161
  typedef struct {
162
    ISeqInStream vt;
163
    InputBuffer *buffer;
164
  } InputBufferStream;
165
166
  static SRes _Read(const ISeqInStream *p, void *data, size_t *size);
167
  SRes Read(void *data, size_t *size);
168
169
  InputBufferStream stream_;
170
  const uint8_t *data_;
171
  size_t size_;
172
};
173
174
InputBuffer::InputBuffer(const uint8_t *data, size_t size)
175
0
  : data_(data), size_(size) {
176
0
  stream_.vt.Read = &InputBuffer::_Read;
177
0
  stream_.buffer = this;
178
0
}
179
180
// static
181
0
SRes InputBuffer::_Read(const ISeqInStream *p, void *data, size_t *size) {
182
0
  InputBufferStream *stream = CONTAINER_FROM_VTBL(p, InputBufferStream, vt);
183
0
  return stream->buffer->Read(data, size);
184
0
}
185
186
0
SRes InputBuffer::Read(void *data, size_t *size) {
187
0
  if (size_ < *size) {
188
0
    *size = size_;
189
0
  }
190
0
  if (*size > 0) {
191
0
    memcpy(data, data_, *size);
192
0
    size_ -= *size;
193
0
    data_ += *size;
194
0
  }
195
0
  return SZ_OK;
196
0
}
197
198
class InputByteBuffer {
199
 public:
200
  InputByteBuffer(const uint8_t *data, size_t size);
201
202
0
  IByteIn *stream() { return &stream_.vt; };
203
204
 private:
205
  typedef struct {
206
    IByteIn vt;
207
    InputByteBuffer *buffer;
208
  } ByteInStream;
209
210
  static Byte _Read(const IByteIn *p);
211
  Byte Read();
212
213
  ByteInStream stream_;
214
  const uint8_t *data_;
215
  size_t size_;
216
  size_t position_ = 0;
217
};
218
219
InputByteBuffer::InputByteBuffer(const uint8_t *data, size_t size)
220
0
  : data_(data), size_(size) {
221
0
  stream_.vt.Read = &InputByteBuffer::_Read;
222
0
  stream_.buffer = this;
223
0
}
224
225
// static
226
0
Byte InputByteBuffer::_Read(const IByteIn *p) {
227
0
  ByteInStream *stream = CONTAINER_FROM_VTBL(p, ByteInStream, vt);
228
0
  return stream->buffer->Read();
229
0
}
230
231
0
Byte InputByteBuffer::Read() {
232
0
  if (size_ == position_) {
233
0
    return 0;
234
0
  }
235
236
0
  return data_[position_++];
237
0
}
238
239
class InputLookBuffer {
240
 public:
241
  InputLookBuffer(const uint8_t *data, size_t size);
242
243
6.33k
  ILookInStream *stream() { return &stream_.vt; };
244
245
 private:
246
  typedef struct {
247
    ILookInStream vt;
248
    InputLookBuffer *buffer;
249
  } InputLookBufferStream;
250
251
  static SRes _Look(const ILookInStream *p, const void **data, size_t *size);
252
  SRes Look(const void **data, size_t *size);
253
  static SRes _Skip(const ILookInStream *p, size_t offset);
254
  SRes Skip(size_t offset);
255
  static SRes _Read(const ILookInStream *p, void *data, size_t *size);
256
  SRes Read(void *data, size_t *size);
257
  static SRes _Seek(const ILookInStream *p, Int64 *pos, ESzSeek origin);
258
  SRes Seek(Int64 *pos, ESzSeek origin);
259
260
  InputLookBufferStream stream_;
261
  const uint8_t *data_;
262
  size_t size_;
263
  size_t position_ = 0;
264
};
265
266
InputLookBuffer::InputLookBuffer(const uint8_t *data, size_t size)
267
4.90k
  : data_(data), size_(size) {
268
4.90k
  stream_.vt.Look = &InputLookBuffer::_Look;
269
4.90k
  stream_.vt.Skip = &InputLookBuffer::_Skip;
270
4.90k
  stream_.vt.Read = &InputLookBuffer::_Read;
271
4.90k
  stream_.vt.Seek = &InputLookBuffer::_Seek;
272
4.90k
  stream_.buffer = this;
273
4.90k
}
274
275
// static
276
SRes InputLookBuffer::_Look(const ILookInStream *p, const void **data,
277
8.29k
    size_t *size) {
278
8.29k
  InputLookBufferStream *stream =
279
8.29k
      CONTAINER_FROM_VTBL(p, InputLookBufferStream, vt);
280
8.29k
  return stream->buffer->Look(data, size);
281
8.29k
}
282
283
8.29k
SRes InputLookBuffer::Look(const void **data, size_t *size) {
284
8.29k
  size_t available = size_ - position_;
285
8.29k
  if (available < *size) {
286
6.53k
    *size = available;
287
6.53k
  }
288
8.29k
  *data = data_ + position_;
289
8.29k
  return SZ_OK;
290
8.29k
}
291
292
// static
293
3.19k
SRes InputLookBuffer::_Skip(const ILookInStream *p, size_t offset) {
294
3.19k
  InputLookBufferStream *stream =
295
3.19k
      CONTAINER_FROM_VTBL(p, InputLookBufferStream, vt);
296
3.19k
  return stream->buffer->Skip(offset);
297
3.19k
}
298
299
3.19k
SRes InputLookBuffer::Skip(size_t offset) {
300
3.19k
  size_t available = size_ - position_;
301
3.19k
  if (offset > available) {
302
0
    offset = available;
303
0
  }
304
3.19k
  position_ += offset;
305
3.19k
  return SZ_OK;
306
3.19k
}
307
308
// static
309
9.48k
SRes InputLookBuffer::_Read(const ILookInStream *p, void *data, size_t *size) {
310
9.48k
  InputLookBufferStream *stream =
311
9.48k
      CONTAINER_FROM_VTBL(p, InputLookBufferStream, vt);
312
9.48k
  return stream->buffer->Read(data, size);
313
9.48k
}
314
315
9.48k
SRes InputLookBuffer::Read(void *data, size_t *size) {
316
9.48k
  size_t available = size_ - position_;
317
9.48k
  if (available < *size) {
318
18
    *size = available;
319
18
  }
320
9.48k
  if (*size > 0) {
321
9.47k
    memcpy(data, data_ + position_, *size);
322
9.47k
    position_ += *size;
323
9.47k
  }
324
9.48k
  return SZ_OK;
325
9.48k
}
326
327
// static
328
SRes InputLookBuffer::_Seek(const ILookInStream *p, Int64 *pos,
329
24.1k
    ESzSeek origin) {
330
24.1k
  InputLookBufferStream *stream =
331
24.1k
      CONTAINER_FROM_VTBL(p, InputLookBufferStream, vt);
332
24.1k
  return stream->buffer->Seek(pos, origin);
333
24.1k
}
334
335
24.1k
SRes InputLookBuffer::Seek(Int64 *pos, ESzSeek origin) {
336
24.1k
  switch (origin) {
337
14.4k
    case SZ_SEEK_SET:
338
14.4k
      if (*pos > size_) {
339
10
        *pos = size_;
340
14.4k
      } else if (*pos < 0) {
341
0
        *pos = 0;
342
0
      }
343
14.4k
      position_ = *pos;
344
14.4k
      break;
345
4.90k
    case SZ_SEEK_CUR:
346
4.90k
      if (*pos > size_ || position_ + *pos > size_) {
347
0
        *pos = size_;
348
4.90k
      } else if (position_ < -*pos) {
349
0
        *pos = 0;
350
0
      }
351
4.90k
      position_ += *pos;
352
4.90k
      break;
353
4.81k
    case SZ_SEEK_END:
354
4.81k
      if (*pos >= 0) {
355
4.81k
        *pos = size_;
356
4.81k
      } else if (-(*pos) > size_) {
357
0
        *pos = 0;
358
0
      } else {
359
0
        *pos = size_ + *pos;
360
0
      }
361
4.81k
      position_ = *pos;
362
4.81k
      break;
363
0
    default:
364
0
      return SZ_ERROR_PARAM;
365
24.1k
  }
366
24.1k
  return SZ_OK;
367
24.1k
}