Coverage Report

Created: 2025-06-13 07:22

/src/libpff/libpff/libpff_index_value.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Index value functions
3
 *
4
 * Copyright (C) 2008-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 "libpff_definitions.h"
28
#include "libpff_index_value.h"
29
#include "libpff_io_handle.h"
30
#include "libpff_libcerror.h"
31
#include "libpff_libcnotify.h"
32
#include "libpff_libfdata.h"
33
34
#include "pff_index_node.h"
35
36
/* Creates an index value
37
 * Make sure the value index_value is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libpff_index_value_initialize(
41
     libpff_index_value_t **index_value,
42
     libcerror_error_t **error )
43
1.24M
{
44
1.24M
  static char *function = "libpff_index_value_initialize";
45
46
1.24M
  if( index_value == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid index value.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
1.24M
  if( *index_value != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid index value value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
1.24M
  *index_value = memory_allocate_structure(
69
1.24M
                  libpff_index_value_t );
70
71
1.24M
  if( *index_value == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create index value.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
1.24M
  if( memory_set(
83
1.24M
       *index_value,
84
1.24M
       0,
85
1.24M
       sizeof( libpff_index_value_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear index value.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
1.24M
  return( 1 );
97
98
0
on_error:
99
0
  if( *index_value != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *index_value );
103
104
0
    *index_value = NULL;
105
0
  }
106
0
  return( -1 );
107
1.24M
}
108
109
/* Frees an index value
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libpff_index_value_free(
113
     libpff_index_value_t **index_value,
114
     libcerror_error_t **error )
115
1.24M
{
116
1.24M
  static char *function = "libpff_index_value_free";
117
118
1.24M
  if( index_value == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid index value.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
1.24M
  if( *index_value != NULL )
130
1.24M
  {
131
1.24M
    memory_free(
132
1.24M
     *index_value );
133
134
1.24M
    *index_value = NULL;
135
1.24M
  }
136
1.24M
  return( 1 );
137
1.24M
}
138
139
/* Compares two index values
140
 * Returns LIBFDATA_COMPARE_LESS, LIBFDATA_COMPARE_EQUAL, LIBFDATA_COMPARE_GREATER if successful or -1 on error
141
 */
142
int libpff_index_value_compare(
143
     libpff_index_value_t *first_index_value,
144
     libpff_index_value_t *second_index_value,
145
     libcerror_error_t **error )
146
0
{
147
0
  static char *function = "libpff_index_value_compare";
148
149
0
  if( first_index_value == NULL )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155
0
     "%s: invalid first index value.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
0
  if( second_index_value == NULL )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
166
0
     "%s: invalid second index value.",
167
0
     function );
168
169
0
    return( -1 );
170
0
  }
171
0
  if( first_index_value->identifier < second_index_value->identifier )
172
0
  {
173
0
    return( LIBFDATA_COMPARE_LESS );
174
0
  }
175
0
  else if( first_index_value->identifier > second_index_value->identifier )
176
0
  {
177
0
    return( LIBFDATA_COMPARE_GREATER );
178
0
  }
179
0
  return( LIBFDATA_COMPARE_EQUAL );
180
0
}
181
182
/* Reads the index value data
183
 * Returns 1 if successful or -1 on error
184
 */
185
int libpff_index_value_read_data(
186
     libpff_index_value_t *index_value,
187
     libpff_io_handle_t *io_handle,
188
     uint8_t index_node_type,
189
     const uint8_t *data,
190
     size_t data_size,
191
     libcerror_error_t **error )
192
1.24M
{
193
1.24M
  static char *function = "libpff_index_value_read_data";
194
1.24M
  size_t value_size     = 0;
195
1.24M
  uint64_t file_offset  = 0;
196
197
1.24M
  if( index_value == NULL )
198
0
  {
199
0
    libcerror_error_set(
200
0
     error,
201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
203
0
     "%s: invalid index value.",
204
0
     function );
205
206
0
    return( -1 );
207
0
  }
208
1.24M
  if( io_handle == NULL )
209
0
  {
210
0
    libcerror_error_set(
211
0
     error,
212
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214
0
     "%s: invalid IO handle.",
215
0
     function );
216
217
0
    return( -1 );
218
0
  }
219
1.24M
  if( index_node_type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
220
1.13M
  {
221
1.13M
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
222
964k
    {
223
964k
      value_size = sizeof( pff_index_node_descriptor_entry_32bit_t );
224
964k
    }
225
169k
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
226
169k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
227
169k
    {
228
169k
      value_size = sizeof( pff_index_node_descriptor_entry_64bit_t );
229
169k
    }
230
1.13M
  }
231
107k
  else if( index_node_type == LIBPFF_INDEX_TYPE_OFFSET )
232
107k
  {
233
107k
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
234
14.0k
    {
235
14.0k
      value_size = sizeof( pff_index_node_offset_entry_32bit_t );
236
14.0k
    }
237
93.3k
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
238
93.3k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
239
93.3k
    {
240
93.3k
      value_size = sizeof( pff_index_node_offset_entry_64bit_t );
241
93.3k
    }
242
107k
  }
243
1.24M
  if( data == NULL )
244
0
  {
245
0
    libcerror_error_set(
246
0
     error,
247
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
248
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
249
0
     "%s: invalid data.",
250
0
     function );
251
252
0
    return( -1 );
253
0
  }
254
1.24M
  if( ( data_size < value_size )
255
1.24M
   || ( data_size > SSIZE_MAX ) )
256
254
  {
257
254
    libcerror_error_set(
258
254
     error,
259
254
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
260
254
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
261
254
     "%s: unsupported data size value out of bounds.",
262
254
     function );
263
264
254
    return( -1 );
265
254
  }
266
#if defined( HAVE_DEBUG_OUTPUT )
267
  if( libcnotify_verbose != 0 )
268
  {
269
    libcnotify_printf(
270
     "%s: index value data:\n",
271
     function );
272
    libcnotify_print_data(
273
     data,
274
     value_size,
275
     0 );
276
  }
277
#endif
278
1.24M
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
279
978k
  {
280
978k
    byte_stream_copy_to_uint32_little_endian(
281
978k
     data,
282
978k
     index_value->identifier );
283
978k
  }
284
263k
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
285
263k
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
286
263k
  {
287
263k
    byte_stream_copy_to_uint64_little_endian(
288
263k
     data,
289
263k
     index_value->identifier );
290
263k
  }
291
  /* Ignore the upper 32-bit of descriptor identifiers
292
   */
293
1.24M
  if( index_node_type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
294
1.13M
  {
295
1.13M
    index_value->identifier &= 0xffffffffUL;
296
1.13M
  }
297
1.24M
  if( index_node_type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
298
1.13M
  {
299
1.13M
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
300
964k
    {
301
964k
      byte_stream_copy_to_uint32_little_endian(
302
964k
       ( (pff_index_node_descriptor_entry_32bit_t *) data )->data_identifier,
303
964k
       index_value->data_identifier );
304
305
964k
      byte_stream_copy_to_uint32_little_endian(
306
964k
       ( (pff_index_node_descriptor_entry_32bit_t *) data )->local_descriptors_identifier,
307
964k
       index_value->local_descriptors_identifier );
308
309
964k
      byte_stream_copy_to_uint32_little_endian(
310
964k
       ( (pff_index_node_descriptor_entry_32bit_t *) data )->parent_identifier,
311
964k
       index_value->parent_identifier );
312
964k
    }
313
169k
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
314
169k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
315
169k
    {
316
169k
      byte_stream_copy_to_uint64_little_endian(
317
169k
       ( (pff_index_node_descriptor_entry_64bit_t *) data )->data_identifier,
318
169k
       index_value->data_identifier );
319
320
169k
      byte_stream_copy_to_uint64_little_endian(
321
169k
       ( (pff_index_node_descriptor_entry_64bit_t *) data )->local_descriptors_identifier,
322
169k
       index_value->local_descriptors_identifier );
323
324
169k
      byte_stream_copy_to_uint32_little_endian(
325
169k
       ( (pff_index_node_descriptor_entry_64bit_t *) data )->parent_identifier,
326
169k
       index_value->parent_identifier );
327
169k
    }
328
1.13M
  }
329
107k
  else if( index_node_type == LIBPFF_INDEX_TYPE_OFFSET )
330
107k
  {
331
107k
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
332
14.0k
    {
333
14.0k
      byte_stream_copy_to_uint32_little_endian(
334
14.0k
       ( (pff_index_node_offset_entry_32bit_t *) data )->file_offset,
335
14.0k
       file_offset );
336
337
14.0k
      byte_stream_copy_to_uint16_little_endian(
338
14.0k
       ( (pff_index_node_offset_entry_32bit_t *) data )->data_size,
339
14.0k
       index_value->data_size );
340
341
14.0k
      byte_stream_copy_to_uint16_little_endian(
342
14.0k
       ( (pff_index_node_offset_entry_32bit_t *) data )->reference_count,
343
14.0k
       index_value->reference_count );
344
14.0k
    }
345
93.1k
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
346
93.1k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
347
93.1k
    {
348
93.1k
      byte_stream_copy_to_uint64_little_endian(
349
93.1k
       ( (pff_index_node_offset_entry_64bit_t *) data )->file_offset,
350
93.1k
       file_offset );
351
352
93.1k
      byte_stream_copy_to_uint16_little_endian(
353
93.1k
       ( (pff_index_node_offset_entry_64bit_t *) data )->data_size,
354
93.1k
       index_value->data_size );
355
356
93.1k
      byte_stream_copy_to_uint16_little_endian(
357
93.1k
       ( (pff_index_node_offset_entry_64bit_t *) data )->reference_count,
358
93.1k
       index_value->reference_count );
359
93.1k
    }
360
107k
  }
361
#if defined( HAVE_DEBUG_OUTPUT )
362
  if( libcnotify_verbose != 0 )
363
  {
364
    libcnotify_printf(
365
     "%s: identifier\t\t\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
366
     function,
367
     index_value->identifier,
368
     index_value->identifier );
369
370
    if( index_node_type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
371
    {
372
      libcnotify_printf(
373
       "%s: data identifier\t\t\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
374
       function,
375
       index_value->data_identifier,
376
       index_value->data_identifier );
377
378
      libcnotify_printf(
379
       "%s: local descriptors identifier\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
380
       function,
381
       index_value->local_descriptors_identifier,
382
       index_value->local_descriptors_identifier );
383
384
      libcnotify_printf(
385
       "%s: parent identifier\t\t\t\t: %" PRIu32 " (0x%08" PRIx32 ")\n",
386
       function,
387
       index_value->parent_identifier,
388
       index_value->parent_identifier );
389
    }
390
    else if( index_node_type == LIBPFF_INDEX_TYPE_OFFSET )
391
    {
392
      libcnotify_printf(
393
       "%s: file offset\t\t\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
394
       function,
395
       file_offset,
396
       file_offset );
397
398
      libcnotify_printf(
399
       "%s: data size\t\t\t\t\t: %" PRIu64 "\n",
400
       function,
401
       index_value->data_size );
402
403
      libcnotify_printf(
404
       "%s: reference count\t\t\t\t: %" PRIu64 "\n",
405
       function,
406
       index_value->reference_count );
407
    }
408
    libcnotify_printf(
409
     "\n" );
410
  }
411
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
412
413
1.24M
  if( index_node_type == LIBPFF_INDEX_TYPE_OFFSET )
414
107k
  {
415
107k
    if( file_offset > (uint64_t) INT64_MAX )
416
439
    {
417
439
      libcerror_error_set(
418
439
       error,
419
439
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
420
439
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
421
439
       "%s: invalid file offset value out of bounds.",
422
439
       function );
423
424
439
      return( -1 );
425
439
    }
426
106k
    index_value->file_offset = file_offset;
427
106k
  }
428
1.24M
  return( 1 );
429
1.24M
}
430