Coverage Report

Created: 2024-02-25 07:20

/src/libmodi/libfmos/libfmos_lzfse_bit_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * LZFSE bit-stream functions
3
 *
4
 * Copyright (C) 2019-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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfmos_libcerror.h"
28
#include "libfmos_libcnotify.h"
29
#include "libfmos_lzfse_bit_stream.h"
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 libfmos_lzfse_bit_stream_initialize(
36
     libfmos_lzfse_bit_stream_t **bit_stream,
37
     const uint8_t *byte_stream,
38
     size_t byte_stream_size,
39
     libcerror_error_t **error )
40
22.3k
{
41
22.3k
  static char *function = "libfmos_lzfse_bit_stream_initialize";
42
43
22.3k
  if( bit_stream == NULL )
44
0
  {
45
0
    libcerror_error_set(
46
0
     error,
47
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49
0
     "%s: invalid bit stream.",
50
0
     function );
51
52
0
    return( -1 );
53
0
  }
54
22.3k
  if( *bit_stream != NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
59
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
60
0
     "%s: invalid bit stream value already set.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
22.3k
  if( byte_stream == NULL )
66
0
  {
67
0
    libcerror_error_set(
68
0
     error,
69
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
70
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
71
0
     "%s: invalid byte stream.",
72
0
     function );
73
74
0
    return( -1 );
75
0
  }
76
22.3k
  if( byte_stream_size > (size_t) SSIZE_MAX )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
82
0
     "%s: invalid byte stream size value exceeds maximum.",
83
0
     function );
84
85
0
    return( -1 );
86
0
  }
87
22.3k
  *bit_stream = memory_allocate_structure(
88
22.3k
                 libfmos_lzfse_bit_stream_t );
89
90
22.3k
  if( *bit_stream == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
95
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
96
0
     "%s: unable to create bit stream.",
97
0
     function );
98
99
0
    goto on_error;
100
0
  }
101
22.3k
  if( memory_set(
102
22.3k
       *bit_stream,
103
22.3k
       0,
104
22.3k
       sizeof( libfmos_lzfse_bit_stream_t ) ) == NULL )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
109
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
110
0
     "%s: unable to clear bit stream.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
22.3k
  ( *bit_stream )->byte_stream        = byte_stream;
116
22.3k
  ( *bit_stream )->byte_stream_size   = byte_stream_size;
117
22.3k
  ( *bit_stream )->byte_stream_offset = byte_stream_size;
118
119
22.3k
  return( 1 );
120
121
0
on_error:
122
0
  if( *bit_stream != NULL )
123
0
  {
124
0
    memory_free(
125
0
     *bit_stream );
126
127
0
    *bit_stream = NULL;
128
0
  }
129
0
  return( -1 );
130
22.3k
}
131
132
/* Frees a bit stream
133
 * Returns 1 if successful or -1 on error
134
 */
135
int libfmos_lzfse_bit_stream_free(
136
     libfmos_lzfse_bit_stream_t **bit_stream,
137
     libcerror_error_t **error )
138
22.3k
{
139
22.3k
  static char *function = "libfmos_lzfse_bit_stream_free";
140
141
22.3k
  if( bit_stream == NULL )
142
0
  {
143
0
    libcerror_error_set(
144
0
     error,
145
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
146
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
147
0
     "%s: invalid bit stream.",
148
0
     function );
149
150
0
    return( -1 );
151
0
  }
152
22.3k
  if( *bit_stream != NULL )
153
22.3k
  {
154
22.3k
    memory_free(
155
22.3k
     *bit_stream );
156
157
22.3k
    *bit_stream = NULL;
158
22.3k
  }
159
22.3k
  return( 1 );
160
22.3k
}
161
162
/* Retrieves a value from the bit stream
163
 * Returns 1 on success or -1 on error
164
 */
165
int libfmos_lzfse_bit_stream_get_value(
166
     libfmos_lzfse_bit_stream_t *bit_stream,
167
     uint8_t number_of_bits,
168
     uint32_t *value_32bit,
169
     libcerror_error_t **error )
170
15.0M
{
171
15.0M
  static char *function            = "libfmos_lzfse_bit_stream_get_value";
172
15.0M
  uint32_t read_value_32bit        = 0;
173
15.0M
  uint32_t safe_value_32bit        = 0;
174
15.0M
  uint8_t read_number_of_bits      = 0;
175
15.0M
  uint8_t remaining_number_of_bits = 0;
176
177
15.0M
  if( bit_stream == NULL )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183
0
     "%s: invalid bit stream.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
15.0M
  if( number_of_bits > (uint8_t) 32 )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
194
0
     "%s: invalid number of bits value exceeds maximum.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
15.0M
  if( value_32bit == NULL )
200
0
  {
201
0
    libcerror_error_set(
202
0
     error,
203
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
204
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
205
0
     "%s: invalid 32-bit value.",
206
0
     function );
207
208
0
    return( -1 );
209
0
  }
210
15.0M
  remaining_number_of_bits = number_of_bits;
211
212
15.1M
  while( remaining_number_of_bits > 0 )
213
49.8k
  {
214
85.0k
    while( ( remaining_number_of_bits > bit_stream->bit_buffer_size )
215
85.0k
        && ( bit_stream->bit_buffer_size <= 24 ) )
216
35.3k
    {
217
35.3k
      if( bit_stream->byte_stream_offset == 0 )
218
90
      {
219
90
        libcerror_error_set(
220
90
         error,
221
90
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
90
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
223
90
         "%s: invalid byte stream offset value out of bounds.",
224
90
         function );
225
226
90
        return( -1 );
227
90
      }
228
35.2k
      bit_stream->byte_stream_offset -= 1;
229
230
35.2k
      bit_stream->bit_buffer     <<= 8;
231
35.2k
      bit_stream->bit_buffer      |= bit_stream->byte_stream[ bit_stream->byte_stream_offset ];
232
35.2k
      bit_stream->bit_buffer_size += 8;
233
35.2k
    }
234
49.7k
    if( remaining_number_of_bits < bit_stream->bit_buffer_size )
235
43.6k
    {
236
43.6k
      read_number_of_bits = remaining_number_of_bits;
237
43.6k
    }
238
6.12k
    else
239
6.12k
    {
240
6.12k
      read_number_of_bits = bit_stream->bit_buffer_size;
241
6.12k
    }
242
49.7k
    read_value_32bit = bit_stream->bit_buffer;
243
244
49.7k
    if( remaining_number_of_bits < number_of_bits )
245
0
    {
246
0
      safe_value_32bit <<= remaining_number_of_bits;
247
0
    }
248
49.7k
    bit_stream->bit_buffer_size -= read_number_of_bits;
249
49.7k
    read_value_32bit           >>= bit_stream->bit_buffer_size;
250
251
49.7k
    if( bit_stream->bit_buffer_size > 0 )
252
43.6k
    {
253
43.6k
      bit_stream->bit_buffer &= 0xffffffffUL >> ( 32 - bit_stream->bit_buffer_size );
254
43.6k
    }
255
6.12k
    else
256
6.12k
    {
257
6.12k
      bit_stream->bit_buffer = 0;
258
6.12k
    }
259
49.7k
    safe_value_32bit         |= read_value_32bit;
260
49.7k
    remaining_number_of_bits -= read_number_of_bits;
261
49.7k
  }
262
15.0M
  *value_32bit = safe_value_32bit;
263
264
15.0M
  return( 1 );
265
15.0M
}
266