Coverage Report

Created: 2024-07-27 06:17

/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
38.5k
  ISeqOutStream *stream() { return &stream_.vt; };
35
31.3k
  const uint8_t *data() const { return data_; }
36
62.9k
  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
38.6k
OutputBuffer::OutputBuffer() {
56
38.6k
  stream_.vt.Write = &OutputBuffer::_Write;
57
38.6k
  stream_.buffer = this;
58
38.6k
}
59
60
38.6k
OutputBuffer::~OutputBuffer() {
61
38.6k
  free(data_);
62
38.6k
}
63
64
// static
65
size_t OutputBuffer::_Write(const ISeqOutStream *p, const void *data,
66
103k
    size_t size) {
67
103k
  OutputBufferStream *stream = CONTAINER_FROM_VTBL(p, OutputBufferStream, vt);
68
103k
  return stream->buffer->Write(data, size);
69
103k
}
70
71
103k
size_t OutputBuffer::Write(const void *data, size_t size) {
72
103k
  size_t available = size_ - position_;
73
103k
  if (available < size) {
74
41.1k
    if (!size_) {
75
35.5k
      size_ = kInitialSize;
76
35.5k
    }
77
99.1k
    while (size_ - position_ < size) {
78
57.9k
      size_ *= 2;
79
57.9k
    }
80
41.1k
    uint8_t *tmp = static_cast<uint8_t*>(malloc(size_));
81
41.1k
    assert(tmp);
82
41.1k
    if (data_) {
83
5.59k
      memcpy(tmp, data_, position_);
84
5.59k
      free(data_);
85
5.59k
    }
86
41.1k
    data_ = tmp;
87
41.1k
  }
88
89
103k
  memcpy(data_ + position_, data, size);
90
103k
  position_ += size;
91
103k
  return size;
92
103k
}
93
94
class OutputByteBuffer {
95
 public:
96
  OutputByteBuffer();
97
  ~OutputByteBuffer();
98
99
1.61k
  IByteOut *stream() { return &stream_.vt; };
100
1.61k
  const uint8_t *data() const { return data_; }
101
3.23k
  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
1.61k
OutputByteBuffer::OutputByteBuffer() {
121
1.61k
  stream_.vt.Write = &OutputByteBuffer::_Write;
122
1.61k
  stream_.buffer = this;
123
1.61k
}
124
125
1.61k
OutputByteBuffer::~OutputByteBuffer() {
126
1.61k
  free(data_);
127
1.61k
}
128
129
// static
130
5.67M
void OutputByteBuffer::_Write(const IByteOut *p, Byte b) {
131
5.67M
  ByteOutStream *stream = CONTAINER_FROM_VTBL(p, ByteOutStream, vt);
132
5.67M
  stream->buffer->Write(b);
133
5.67M
}
134
135
5.67M
void OutputByteBuffer::Write(Byte b) {
136
5.67M
  if (size_ == position_) {
137
2.45k
    if (!size_) {
138
1.61k
      size_ = kInitialSize;
139
1.61k
    } else {
140
840
      size_ *= 2;
141
840
    }
142
2.45k
    uint8_t *tmp = static_cast<uint8_t*>(malloc(size_));
143
2.45k
    assert(tmp);
144
2.45k
    if (data_) {
145
840
      memcpy(tmp, data_, position_);
146
840
      free(data_);
147
840
    }
148
2.45k
    data_ = tmp;
149
2.45k
  }
150
151
5.67M
  data_[position_++] = b;
152
5.67M
}
153
154
class InputBuffer {
155
 public:
156
  InputBuffer(const uint8_t *data, size_t size);
157
158
38.5k
  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
38.6k
  : data_(data), size_(size) {
176
38.6k
  stream_.vt.Read = &InputBuffer::_Read;
177
38.6k
  stream_.buffer = this;
178
38.6k
}
179
180
// static
181
75.7k
SRes InputBuffer::_Read(const ISeqInStream *p, void *data, size_t *size) {
182
75.7k
  InputBufferStream *stream = CONTAINER_FROM_VTBL(p, InputBufferStream, vt);
183
75.7k
  return stream->buffer->Read(data, size);
184
75.7k
}
185
186
75.7k
SRes InputBuffer::Read(void *data, size_t *size) {
187
75.7k
  if (size_ < *size) {
188
74.8k
    *size = size_;
189
74.8k
  }
190
75.7k
  if (*size > 0) {
191
39.4k
    memcpy(data, data_, *size);
192
39.4k
    size_ -= *size;
193
39.4k
    data_ += *size;
194
39.4k
  }
195
75.7k
  return SZ_OK;
196
75.7k
}
197
198
class InputByteBuffer {
199
 public:
200
  InputByteBuffer(const uint8_t *data, size_t size);
201
202
1.61k
  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
1.61k
  : data_(data), size_(size) {
221
1.61k
  stream_.vt.Read = &InputByteBuffer::_Read;
222
1.61k
  stream_.buffer = this;
223
1.61k
}
224
225
// static
226
5.67M
Byte InputByteBuffer::_Read(const IByteIn *p) {
227
5.67M
  ByteInStream *stream = CONTAINER_FROM_VTBL(p, ByteInStream, vt);
228
5.67M
  return stream->buffer->Read();
229
5.67M
}
230
231
5.67M
Byte InputByteBuffer::Read() {
232
5.67M
  if (size_ == position_) {
233
0
    return 0;
234
0
  }
235
236
5.67M
  return data_[position_++];
237
5.67M
}
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
}