Coverage Report

Created: 2025-06-24 07:14

/src/libqcow/libqcow/libqcow_bit_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Bit-stream functions
3
 *
4
 * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libqcow_bit_stream.h"
27
#include "libqcow_libcerror.h"
28
29
/* TODO use memory alignment in bit stream */
30
31
/* Creates a bit stream
32
 * Make sure the value bit_stream is referencing, is set to NULL
33
 * Returns 1 if successful or -1 on error
34
 */
35
int libqcow_bit_stream_initialize(
36
     libqcow_bit_stream_t **bit_stream,
37
     const uint8_t *byte_stream,
38
     size_t byte_stream_size,
39
     size_t byte_stream_offset,
40
     uint8_t storage_type,
41
     libcerror_error_t **error )
42
0
{
43
0
  static char *function = "libqcow_bit_stream_initialize";
44
45
0
  if( bit_stream == NULL )
46
0
  {
47
0
    libcerror_error_set(
48
0
     error,
49
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51
0
     "%s: invalid bit stream.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
0
  if( *bit_stream != NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
61
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62
0
     "%s: invalid bit stream value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
0
  if( byte_stream == NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
72
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
73
0
     "%s: invalid byte stream.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
0
  if( byte_stream_size > (size_t) SSIZE_MAX )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
83
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
84
0
     "%s: invalid byte stream size value exceeds maximum.",
85
0
     function );
86
87
0
    return( -1 );
88
0
  }
89
0
  if( byte_stream_offset > (size_t) SSIZE_MAX )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
94
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
95
0
     "%s: invalid byte stream offset value exceeds maximum.",
96
0
     function );
97
98
0
    return( -1 );
99
0
  }
100
0
  if( ( storage_type != LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_BACK_TO_FRONT )
101
0
   && ( storage_type != LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_FRONT_TO_BACK ) )
102
0
  {
103
0
    libcerror_error_set(
104
0
     error,
105
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
106
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
107
0
     "%s: unsupported storage type.",
108
0
     function );
109
110
0
    return( -1 );
111
0
  }
112
0
  *bit_stream = memory_allocate_structure(
113
0
                 libqcow_bit_stream_t );
114
115
0
  if( *bit_stream == NULL )
116
0
  {
117
0
    libcerror_error_set(
118
0
     error,
119
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
120
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
121
0
     "%s: unable to create bit stream.",
122
0
     function );
123
124
0
    goto on_error;
125
0
  }
126
0
  if( memory_set(
127
0
       *bit_stream,
128
0
       0,
129
0
       sizeof( libqcow_bit_stream_t ) ) == NULL )
130
0
  {
131
0
    libcerror_error_set(
132
0
     error,
133
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
134
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
135
0
     "%s: unable to clear bit stream.",
136
0
     function );
137
138
0
    goto on_error;
139
0
  }
140
0
  ( *bit_stream )->byte_stream        = byte_stream;
141
0
  ( *bit_stream )->byte_stream_size   = byte_stream_size;
142
0
  ( *bit_stream )->byte_stream_offset = byte_stream_offset;
143
0
  ( *bit_stream )->storage_type       = storage_type;
144
145
0
  return( 1 );
146
147
0
on_error:
148
0
  if( *bit_stream != NULL )
149
0
  {
150
0
    memory_free(
151
0
     *bit_stream );
152
153
0
    *bit_stream = NULL;
154
0
  }
155
0
  return( -1 );
156
0
}
157
158
/* Frees a bit stream
159
 * Returns 1 if successful or -1 on error
160
 */
161
int libqcow_bit_stream_free(
162
     libqcow_bit_stream_t **bit_stream,
163
     libcerror_error_t **error )
164
0
{
165
0
  static char *function = "libqcow_bit_stream_free";
166
167
0
  if( bit_stream == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid bit stream.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
0
  if( *bit_stream != NULL )
179
0
  {
180
0
    memory_free(
181
0
     *bit_stream );
182
183
0
    *bit_stream = NULL;
184
0
  }
185
0
  return( 1 );
186
0
}
187
188
/* Retrieves a value from the bit stream
189
 * Returns 1 on success or -1 on error
190
 */
191
int libqcow_bit_stream_get_value(
192
     libqcow_bit_stream_t *bit_stream,
193
     uint8_t number_of_bits,
194
     uint32_t *value_32bit,
195
     libcerror_error_t **error )
196
0
{
197
0
  static char *function            = "libqcow_bit_stream_get_value";
198
0
  uint32_t read_value_32bit        = 0;
199
0
  uint32_t safe_value_32bit        = 0;
200
0
  uint8_t read_number_of_bits      = 0;
201
0
  uint8_t remaining_number_of_bits = 0;
202
203
0
  if( bit_stream == NULL )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
209
0
     "%s: invalid bit stream.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
0
  if( number_of_bits > (uint8_t) 32 )
215
0
  {
216
0
    libcerror_error_set(
217
0
     error,
218
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
219
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
220
0
     "%s: invalid number of bits value exceeds maximum.",
221
0
     function );
222
223
0
    return( -1 );
224
0
  }
225
0
  if( value_32bit == NULL )
226
0
  {
227
0
    libcerror_error_set(
228
0
     error,
229
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
230
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
231
0
     "%s: invalid 32-bit value.",
232
0
     function );
233
234
0
    return( -1 );
235
0
  }
236
0
  remaining_number_of_bits = number_of_bits;
237
238
0
  while( remaining_number_of_bits > 0 )
239
0
  {
240
0
    while( ( remaining_number_of_bits > bit_stream->bit_buffer_size )
241
0
        && ( bit_stream->bit_buffer_size <= 24 ) )
242
0
    {
243
0
      if( bit_stream->byte_stream_offset >= bit_stream->byte_stream_size )
244
0
      {
245
0
        libcerror_error_set(
246
0
         error,
247
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
249
0
         "%s: invalid byte stream offset value out of bounds.",
250
0
         function );
251
252
0
        return( -1 );
253
0
      }
254
0
      if( bit_stream->storage_type == LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_BACK_TO_FRONT )
255
0
      {
256
0
        bit_stream->bit_buffer |= (uint32_t) bit_stream->byte_stream[ bit_stream->byte_stream_offset ] << bit_stream->bit_buffer_size;
257
0
      }
258
0
      else if( bit_stream->storage_type == LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_FRONT_TO_BACK )
259
0
      {
260
0
        bit_stream->bit_buffer <<= 8;
261
0
        bit_stream->bit_buffer  |= bit_stream->byte_stream[ bit_stream->byte_stream_offset ];
262
0
      }
263
0
      bit_stream->bit_buffer_size    += 8;
264
0
      bit_stream->byte_stream_offset += 1;
265
0
    }
266
0
    if( remaining_number_of_bits < bit_stream->bit_buffer_size )
267
0
    {
268
0
      read_number_of_bits = remaining_number_of_bits;
269
0
    }
270
0
    else
271
0
    {
272
0
      read_number_of_bits = bit_stream->bit_buffer_size;
273
0
    }
274
0
    read_value_32bit = bit_stream->bit_buffer;
275
276
0
    if( remaining_number_of_bits < number_of_bits )
277
0
    {
278
0
      safe_value_32bit <<= remaining_number_of_bits;
279
0
    }
280
0
    if( bit_stream->storage_type == LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_BACK_TO_FRONT )
281
0
    {
282
0
      if( read_number_of_bits < 32 )
283
0
      {
284
        /* On VS 2008 32-bit "~( 0xfffffffUL << 32 )" does not behave as expected
285
         */
286
0
        read_value_32bit &= ~( 0xffffffffUL << read_number_of_bits );
287
288
0
        bit_stream->bit_buffer >>= read_number_of_bits;
289
0
      }
290
0
      bit_stream->bit_buffer_size -= read_number_of_bits;
291
0
    }
292
0
    else if( bit_stream->storage_type == LIBQCOW_BIT_STREAM_STORAGE_TYPE_BYTE_FRONT_TO_BACK )
293
0
    {
294
0
      bit_stream->bit_buffer_size -= read_number_of_bits;
295
0
      read_value_32bit           >>= bit_stream->bit_buffer_size;
296
297
0
      if( bit_stream->bit_buffer_size > 0 )
298
0
      {
299
0
        bit_stream->bit_buffer &= 0xffffffffUL >> ( 32 - bit_stream->bit_buffer_size );
300
0
      }
301
0
    }
302
0
    if( bit_stream->bit_buffer_size == 0 )
303
0
    {
304
0
      bit_stream->bit_buffer = 0;
305
0
    }
306
0
    safe_value_32bit         |= read_value_32bit;
307
0
    remaining_number_of_bits -= read_number_of_bits;
308
0
  }
309
0
  *value_32bit = safe_value_32bit;
310
311
0
  return( 1 );
312
0
}
313