Coverage Report

Created: 2024-02-25 07:20

/src/libfsntfs/libfwnt/libfwnt_bit_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Bit-stream functions
3
 *
4
 * Copyright (C) 2009-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 "libfwnt_bit_stream.h"
27
#include "libfwnt_libcerror.h"
28
29
/* Creates a bit stream
30
 * Make sure the value bit_stream is referencing, is set to NULL
31
 * Returns 1 if successful or -1 on error
32
 */
33
int libfwnt_bit_stream_initialize(
34
     libfwnt_bit_stream_t **bit_stream,
35
     const uint8_t *byte_stream,
36
     size_t byte_stream_size,
37
     libcerror_error_t **error )
38
2.40k
{
39
2.40k
  static char *function = "libfwnt_bit_stream_initialize";
40
41
2.40k
  if( bit_stream == NULL )
42
0
  {
43
0
    libcerror_error_set(
44
0
     error,
45
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
46
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
47
0
     "%s: invalid bit stream.",
48
0
     function );
49
50
0
    return( -1 );
51
0
  }
52
2.40k
  if( *bit_stream != NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
57
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
58
0
     "%s: invalid bit stream value already set.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
2.40k
  if( byte_stream == NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
68
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
69
0
     "%s: invalid byte stream value.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
2.40k
  if( byte_stream_size > (size_t) SSIZE_MAX )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
79
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
80
0
     "%s: byte stream size value exceeds maximum.",
81
0
     function );
82
83
0
    return( -1 );
84
0
  }
85
2.40k
  *bit_stream = memory_allocate_structure(
86
2.40k
                 libfwnt_bit_stream_t );
87
88
2.40k
  if( *bit_stream == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
94
0
     "%s: unable to create bit stream.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
2.40k
  if( memory_set(
100
2.40k
       *bit_stream,
101
2.40k
       0,
102
2.40k
       sizeof( libfwnt_bit_stream_t ) ) == NULL )
103
0
  {
104
0
    libcerror_error_set(
105
0
     error,
106
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
107
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
108
0
     "%s: unable to clear bit stream.",
109
0
     function );
110
111
0
    goto on_error;
112
0
  }
113
2.40k
  ( *bit_stream )->byte_stream      = byte_stream;
114
2.40k
  ( *bit_stream )->byte_stream_size = byte_stream_size;
115
116
2.40k
  return( 1 );
117
118
0
on_error:
119
0
  if( *bit_stream != NULL )
120
0
  {
121
0
    memory_free(
122
0
     *bit_stream );
123
124
0
    *bit_stream = NULL;
125
0
  }
126
0
  return( -1 );
127
2.40k
}
128
129
/* Frees a bit stream
130
 * Returns 1 if successful or -1 on error
131
 */
132
int libfwnt_bit_stream_free(
133
     libfwnt_bit_stream_t **bit_stream,
134
     libcerror_error_t **error )
135
2.40k
{
136
2.40k
  static char *function = "libfwnt_bit_stream_free";
137
138
2.40k
  if( bit_stream == NULL )
139
0
  {
140
0
    libcerror_error_set(
141
0
     error,
142
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
144
0
     "%s: invalid bit stream.",
145
0
     function );
146
147
0
    return( -1 );
148
0
  }
149
2.40k
  if( *bit_stream != NULL )
150
2.40k
  {
151
2.40k
    memory_free(
152
2.40k
     *bit_stream );
153
154
2.40k
    *bit_stream = NULL;
155
2.40k
  }
156
2.40k
  return( 1 );
157
2.40k
}
158
159
/* Reads bits from the underlying byte stream
160
 * Returns 1 on success or -1 on error
161
 */
162
int libfwnt_bit_stream_read(
163
     libfwnt_bit_stream_t *bit_stream,
164
     uint8_t number_of_bits,
165
     libcerror_error_t **error )
166
10.3M
{
167
10.3M
  static char *function = "libfwnt_bit_stream_read";
168
169
10.3M
  if( bit_stream == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid bit stream.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
10.3M
  if( ( number_of_bits == 0 )
181
10.3M
   || ( number_of_bits > 32 ) )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
187
0
     "%s: number of bits value out of bounds.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
20.6M
  while( bit_stream->bit_buffer_size < number_of_bits )
193
10.3M
  {
194
10.3M
    if( ( bit_stream->byte_stream_size < 2 )
195
10.3M
     || ( bit_stream->byte_stream_offset > ( bit_stream->byte_stream_size - 2 ) ) )
196
2.53M
    {
197
      /* If the bit stream overflows fill the bit buffer with 0 byte values
198
       */
199
2.53M
      bit_stream->bit_buffer     <<= 16;
200
2.53M
      bit_stream->bit_buffer_size += 16;
201
2.53M
    }
202
7.78M
    else
203
7.78M
    {
204
7.78M
      bit_stream->bit_buffer     <<= 8;
205
7.78M
      bit_stream->bit_buffer      |= bit_stream->byte_stream[ bit_stream->byte_stream_offset + 1 ];
206
7.78M
      bit_stream->bit_buffer     <<= 8;
207
7.78M
      bit_stream->bit_buffer      |= bit_stream->byte_stream[ bit_stream->byte_stream_offset ];
208
7.78M
      bit_stream->bit_buffer_size += 16;
209
210
7.78M
      bit_stream->byte_stream_offset += 2;
211
7.78M
    }
212
10.3M
  }
213
10.3M
  return( 1 );
214
10.3M
}
215
216
/* Retrieves a value from the bit stream
217
 * Returns 1 on success or -1 on error
218
 */
219
int libfwnt_bit_stream_get_value(
220
     libfwnt_bit_stream_t *bit_stream,
221
     uint8_t number_of_bits,
222
     uint32_t *value_32bit,
223
     libcerror_error_t **error )
224
135M
{
225
135M
  static char *function             = "libfwnt_bit_stream_get_value";
226
135M
  uint32_t safe_value_32bit         = 0;
227
135M
  uint8_t remaining_bit_buffer_size = 0;
228
229
135M
  if( bit_stream == NULL )
230
0
  {
231
0
    libcerror_error_set(
232
0
     error,
233
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
234
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
235
0
     "%s: invalid bit stream.",
236
0
     function );
237
238
0
    return( -1 );
239
0
  }
240
135M
  if( number_of_bits > (uint8_t) 32 )
241
0
  {
242
0
    libcerror_error_set(
243
0
     error,
244
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
245
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
246
0
     "%s: invalid number of bits value exceeds maximum.",
247
0
     function );
248
249
0
    return( -1 );
250
0
  }
251
135M
  if( value_32bit == NULL )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
256
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
257
0
     "%s: invalid 32-bit value.",
258
0
     function );
259
260
0
    return( -1 );
261
0
  }
262
135M
  if( number_of_bits == 0 )
263
37.1k
  {
264
37.1k
    *value_32bit = 0;
265
266
37.1k
    return( 1 );
267
37.1k
  }
268
135M
  if( bit_stream->bit_buffer_size < number_of_bits )
269
53.9k
  {
270
53.9k
    if( libfwnt_bit_stream_read(
271
53.9k
         bit_stream,
272
53.9k
         number_of_bits,
273
53.9k
         error ) != 1 )
274
0
    {
275
0
      libcerror_error_set(
276
0
       error,
277
0
       LIBCERROR_ERROR_DOMAIN_IO,
278
0
       LIBCERROR_IO_ERROR_READ_FAILED,
279
0
       "%s: unable to read bits.",
280
0
       function );
281
282
0
      return( -1 );
283
0
    }
284
53.9k
  }
285
135M
  safe_value_32bit = bit_stream->bit_buffer;
286
287
135M
  if( number_of_bits < 32 )
288
135M
  {
289
135M
    safe_value_32bit >>= bit_stream->bit_buffer_size - number_of_bits;
290
135M
  }
291
135M
  bit_stream->bit_buffer_size -= number_of_bits;
292
293
  /* The behavior of "bit_buffer & ( 0xfffffffUL >> 32 )" differs for some compilers.
294
   */
295
135M
  if( bit_stream->bit_buffer_size == 0 )
296
197k
  {
297
197k
    bit_stream->bit_buffer = 0;
298
197k
  }
299
135M
  else
300
135M
  {
301
135M
    remaining_bit_buffer_size = 32 - bit_stream->bit_buffer_size;
302
135M
    bit_stream->bit_buffer   &= 0xffffffffUL >> remaining_bit_buffer_size;
303
135M
  }
304
135M
  *value_32bit = safe_value_32bit;
305
306
135M
  return( 1 );
307
135M
}
308