Coverage Report

Created: 2026-01-20 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpff/libpff/libpff_local_descriptors_node.c
Line
Count
Source
1
/*
2
 * Local descriptors node functions
3
 *
4
 * Copyright (C) 2008-2025, 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_data_block.h"
28
#include "libpff_definitions.h"
29
#include "libpff_io_handle.h"
30
#include "libpff_libbfio.h"
31
#include "libpff_libcerror.h"
32
#include "libpff_libcnotify.h"
33
#include "libpff_local_descriptors_node.h"
34
35
#include "pff_local_descriptors_node.h"
36
37
/* Creates a local descriptors node
38
 * Make sure the value local_descriptors_node is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libpff_local_descriptors_node_initialize(
42
     libpff_local_descriptors_node_t **local_descriptors_node,
43
     libcerror_error_t **error )
44
13.9k
{
45
13.9k
  static char *function = "libpff_local_descriptors_node_initialize";
46
47
13.9k
  if( local_descriptors_node == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid local descriptors node.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
13.9k
  if( *local_descriptors_node != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid local descriptors node value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
13.9k
  *local_descriptors_node = memory_allocate_structure(
70
13.9k
                             libpff_local_descriptors_node_t );
71
72
13.9k
  if( *local_descriptors_node == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
77
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78
0
     "%s: unable to create local descriptors node.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
13.9k
  if( memory_set(
84
13.9k
       *local_descriptors_node,
85
13.9k
       0,
86
13.9k
       sizeof( libpff_local_descriptors_node_t ) ) == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
92
0
     "%s: unable to clear local descriptors node.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
13.9k
  return( 1 );
98
99
0
on_error:
100
0
  if( *local_descriptors_node != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *local_descriptors_node );
104
105
0
    *local_descriptors_node = NULL;
106
0
  }
107
0
  return( -1 );
108
13.9k
}
109
110
/* Frees a local descriptors node
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libpff_local_descriptors_node_free(
114
     libpff_local_descriptors_node_t **local_descriptors_node,
115
     libcerror_error_t **error )
116
13.9k
{
117
13.9k
  static char *function = "libpff_local_descriptors_node_free";
118
119
13.9k
  if( local_descriptors_node == NULL )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
124
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
125
0
     "%s: invalid local descriptors node.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
13.9k
  if( *local_descriptors_node != NULL )
131
13.9k
  {
132
13.9k
    if( ( *local_descriptors_node )->entries_data != NULL )
133
13.6k
    {
134
13.6k
      memory_free(
135
13.6k
       ( *local_descriptors_node )->entries_data );
136
13.6k
    }
137
13.9k
    memory_free(
138
13.9k
     *local_descriptors_node );
139
140
13.9k
    *local_descriptors_node = NULL;
141
13.9k
  }
142
13.9k
  return( 1 );
143
13.9k
}
144
145
/* Retrieves the data of a specific entry
146
 * Returns 1 if successful or -1 on error
147
 */
148
int libpff_local_descriptors_node_get_entry_data(
149
     libpff_local_descriptors_node_t *local_descriptors_node,
150
     uint16_t entry_index,
151
     uint8_t **entry_data,
152
     libcerror_error_t **error )
153
28.2k
{
154
28.2k
  static char *function = "libpff_local_descriptors_node_get_entry_data";
155
28.2k
  size_t entry_offset   = 0;
156
157
28.2k
  if( local_descriptors_node == NULL )
158
293
  {
159
293
    libcerror_error_set(
160
293
     error,
161
293
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
162
293
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
163
293
     "%s: invalid local descriptors node.",
164
293
     function );
165
166
293
    return( -1 );
167
293
  }
168
27.9k
  if( local_descriptors_node->entries_data == NULL )
169
0
  {
170
0
    libcerror_error_set(
171
0
     error,
172
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
173
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
174
0
     "%s: invalid local descriptors node - missing entries data.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
27.9k
  if( entry_data == NULL )
180
0
  {
181
0
    libcerror_error_set(
182
0
     error,
183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
184
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
185
0
     "%s: invalid entry data.",
186
0
     function );
187
188
0
    return( -1 );
189
0
  }
190
27.9k
  entry_offset = (size_t) ( local_descriptors_node->entry_size * entry_index );
191
192
27.9k
  if( entry_offset > local_descriptors_node->entries_data_size )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
198
0
     "%s: entry index value exceeds maximum.",
199
0
     function );
200
201
0
    return( -1 );
202
0
  }
203
27.9k
  *entry_data = &( local_descriptors_node->entries_data[ entry_offset ] );
204
205
27.9k
  return( 1 );
206
27.9k
}
207
208
/* Retrieves the identifier of a specific entry
209
 * Returns 1 if successful or -1 on error
210
 */
211
int libpff_local_descriptors_node_get_entry_identifier(
212
     libpff_local_descriptors_node_t *local_descriptors_node,
213
     libpff_io_handle_t *io_handle,
214
     uint16_t entry_index,
215
     uint64_t *entry_identifier,
216
     libcerror_error_t **error )
217
0
{
218
0
  uint8_t *node_entry_data = NULL;
219
0
  static char *function    = "libpff_local_descriptors_node_get_entry_identifier";
220
0
  size_t entry_offset      = 0;
221
222
0
  if( local_descriptors_node == NULL )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
228
0
     "%s: invalid local descriptors node.",
229
0
     function );
230
231
0
    return( -1 );
232
0
  }
233
0
  if( local_descriptors_node->entries_data == NULL )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
238
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
239
0
     "%s: invalid local descriptors node - missing entries data.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
0
  if( io_handle == NULL )
245
0
  {
246
0
    libcerror_error_set(
247
0
     error,
248
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
249
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
250
0
     "%s: invalid IO handle.",
251
0
     function );
252
253
0
    return( -1 );
254
0
  }
255
0
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
256
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
257
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
263
0
     "%s: invalid IO handle - unsupported file type.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
0
  if( entry_identifier == NULL )
269
0
  {
270
0
    libcerror_error_set(
271
0
     error,
272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274
0
     "%s: invalid entry identifier.",
275
0
     function );
276
277
0
    return( -1 );
278
0
  }
279
0
  entry_offset = (size_t) ( local_descriptors_node->entry_size * entry_index );
280
281
0
  if( entry_offset > local_descriptors_node->entries_data_size )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
286
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
287
0
     "%s: entry index value exceeds maximum.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
0
  node_entry_data = &( local_descriptors_node->entries_data[ entry_offset ] );
293
294
0
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
295
0
  {
296
0
    byte_stream_copy_to_uint32_little_endian(
297
0
     node_entry_data,
298
0
     *entry_identifier );
299
0
  }
300
0
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
301
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
302
0
  {
303
0
    byte_stream_copy_to_uint64_little_endian(
304
0
     node_entry_data,
305
0
     *entry_identifier );
306
0
  }
307
0
  return( 1 );
308
0
}
309
310
/* Retrieves the sub node identifier of a specific entry
311
 * Returns 1 if successful or -1 on error
312
 */
313
int libpff_local_descriptors_node_get_entry_sub_node_identifier(
314
     libpff_local_descriptors_node_t *local_descriptors_node,
315
     libpff_io_handle_t *io_handle,
316
     uint16_t entry_index,
317
     uint64_t *entry_sub_node_identifier,
318
     libcerror_error_t **error )
319
0
{
320
0
  uint8_t *node_entry_data = NULL;
321
0
  static char *function    = "libpff_local_descriptors_node_get_entry_sub_node_identifier";
322
0
  size_t entry_offset      = 0;
323
324
0
  if( local_descriptors_node == NULL )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
329
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
330
0
     "%s: invalid local descriptors node.",
331
0
     function );
332
333
0
    return( -1 );
334
0
  }
335
0
  if( local_descriptors_node->entries_data == NULL )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
340
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
341
0
     "%s: invalid local descriptors node - missing entries data.",
342
0
     function );
343
344
0
    return( -1 );
345
0
  }
346
0
  if( io_handle == NULL )
347
0
  {
348
0
    libcerror_error_set(
349
0
     error,
350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
351
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
352
0
     "%s: invalid IO handle.",
353
0
     function );
354
355
0
    return( -1 );
356
0
  }
357
0
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
358
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
359
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
360
0
  {
361
0
    libcerror_error_set(
362
0
     error,
363
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
364
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
365
0
     "%s: invalid IO handle - unsupported file type.",
366
0
     function );
367
368
0
    return( -1 );
369
0
  }
370
0
  if( entry_sub_node_identifier == NULL )
371
0
  {
372
0
    libcerror_error_set(
373
0
     error,
374
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
375
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
376
0
     "%s: invalid entry sub node identifier.",
377
0
     function );
378
379
0
    return( -1 );
380
0
  }
381
0
  entry_offset = (size_t) ( local_descriptors_node->entry_size * entry_index );
382
383
0
  if( entry_offset > local_descriptors_node->entries_data_size )
384
0
  {
385
0
    libcerror_error_set(
386
0
     error,
387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
388
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
389
0
     "%s: entry index value exceeds maximum.",
390
0
     function );
391
392
0
    return( -1 );
393
0
  }
394
0
  node_entry_data = &( local_descriptors_node->entries_data[ entry_offset ] );
395
396
0
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
397
0
  {
398
0
    byte_stream_copy_to_uint32_little_endian(
399
0
     ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->sub_node_identifier,
400
0
     *entry_sub_node_identifier );
401
0
  }
402
0
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
403
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
404
0
  {
405
0
    byte_stream_copy_to_uint64_little_endian(
406
0
     ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->sub_node_identifier,
407
0
     *entry_sub_node_identifier );
408
0
  }
409
0
  return( 1 );
410
0
}
411
412
/* Reads a local descriptors node
413
 * Returns 1 if successful or -1 on error
414
 */
415
int libpff_local_descriptors_node_read_data(
416
     libpff_local_descriptors_node_t *local_descriptors_node,
417
     libpff_io_handle_t *io_handle,
418
     const uint8_t *data,
419
     size_t data_size,
420
     libcerror_error_t **error )
421
13.7k
{
422
13.7k
  static char *function                      = "libpff_local_descriptors_node_read_data";
423
13.7k
  size_t header_data_size                    = 0;
424
13.7k
  uint8_t node_signature                     = 0;
425
426
#if defined( HAVE_DEBUG_OUTPUT )
427
  uint8_t *local_descriptors_node_entry_data = NULL;
428
  uint64_t value_64bit                       = 0;
429
  uint16_t entry_index                       = 0;
430
#endif
431
432
13.7k
  if( local_descriptors_node == NULL )
433
0
  {
434
0
    libcerror_error_set(
435
0
     error,
436
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
437
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
438
0
     "%s: invalid local descriptors node.",
439
0
     function );
440
441
0
    return( -1 );
442
0
  }
443
13.7k
  if( local_descriptors_node->entries_data != NULL )
444
0
  {
445
0
    libcerror_error_set(
446
0
     error,
447
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
448
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
449
0
     "%s: invalid local descriptors node - entries data value already set.",
450
0
     function );
451
452
0
    return( -1 );
453
0
  }
454
13.7k
  if( io_handle == NULL )
455
0
  {
456
0
    libcerror_error_set(
457
0
     error,
458
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
459
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
460
0
     "%s: invalid IO handle.",
461
0
     function );
462
463
0
    return( -1 );
464
0
  }
465
13.7k
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
466
134
  {
467
134
    header_data_size = sizeof( pff_local_descriptors_node_32bit_t );
468
134
  }
469
13.6k
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
470
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
471
13.6k
  {
472
13.6k
    header_data_size = sizeof( pff_local_descriptors_node_64bit_t );
473
13.6k
  }
474
0
  else
475
0
  {
476
0
    libcerror_error_set(
477
0
     error,
478
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
479
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
480
0
     "%s: invalid IO handle - unsupported file type.",
481
0
     function );
482
483
0
    return( -1 );
484
0
  }
485
13.7k
  if( data == NULL )
486
24
  {
487
24
    libcerror_error_set(
488
24
     error,
489
24
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
490
24
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
491
24
     "%s: invalid data.",
492
24
     function );
493
494
24
    return( -1 );
495
24
  }
496
13.7k
  if( ( data_size < header_data_size )
497
13.7k
   || ( data_size > SSIZE_MAX ) )
498
6
  {
499
6
    libcerror_error_set(
500
6
     error,
501
6
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
502
6
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
503
6
     "%s: unsupported data size value out of bounds.",
504
6
     function );
505
506
6
    return( -1 );
507
6
  }
508
#if defined( HAVE_DEBUG_OUTPUT )
509
  if( libcnotify_verbose != 0 )
510
  {
511
    libcnotify_printf(
512
     "%s: local descriptors node data:\n",
513
     function );
514
    libcnotify_print_data(
515
     data,
516
     data_size,
517
     0 );
518
  }
519
#endif
520
13.7k
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
521
127
  {
522
127
    node_signature               = ( (pff_local_descriptors_node_32bit_t *) data )->signature;
523
127
    local_descriptors_node->level = ( (pff_local_descriptors_node_32bit_t *) data )->level;
524
525
127
    byte_stream_copy_to_uint16_little_endian(
526
127
     ( (pff_local_descriptors_node_32bit_t *) data )->number_of_entries,
527
127
     local_descriptors_node->number_of_entries );
528
127
  }
529
13.6k
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
530
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
531
13.6k
  {
532
13.6k
    node_signature               = ( (pff_local_descriptors_node_64bit_t *) data )->signature;
533
13.6k
    local_descriptors_node->level = ( (pff_local_descriptors_node_64bit_t *) data )->level;
534
535
13.6k
    byte_stream_copy_to_uint16_little_endian(
536
13.6k
     ( (pff_local_descriptors_node_64bit_t *) data )->number_of_entries,
537
13.6k
     local_descriptors_node->number_of_entries );
538
13.6k
  }
539
#if defined( HAVE_DEBUG_OUTPUT )
540
  if( libcnotify_verbose != 0 )
541
  {
542
    libcnotify_printf(
543
     "%s: local descriptors node signature\t\t: 0x%02" PRIx8 "\n",
544
     function,
545
     node_signature );
546
547
    libcnotify_printf(
548
     "%s: local descriptors node level\t\t\t: %" PRIu8 "\n",
549
     function,
550
     local_descriptors_node->level );
551
552
    libcnotify_printf(
553
     "%s: number of entries\t\t\t\t: %" PRIu16 "\n",
554
     function,
555
     local_descriptors_node->number_of_entries );
556
557
    if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
558
     || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
559
    {
560
      libcnotify_printf(
561
       "%s: padding1:\n",
562
       function );
563
      libcnotify_print_data(
564
       ( (pff_local_descriptors_node_64bit_t *) data )->padding1,
565
       4,
566
       0 );
567
    }
568
  }
569
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
570
571
13.7k
  if( node_signature != 0x02 )
572
43
  {
573
43
    libcerror_error_set(
574
43
     error,
575
43
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
576
43
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
577
43
     "%s: unsupported local descriptors node signature: 0x%02" PRIx8 ".",
578
43
     function,
579
43
     node_signature );
580
581
43
    goto on_error;
582
43
  }
583
13.7k
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
584
108
  {
585
108
    if( local_descriptors_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
586
6
    {
587
6
      local_descriptors_node->entry_size = sizeof( pff_local_descriptor_leaf_node_entry_type_32bit_t );
588
6
    }
589
102
    else
590
102
    {
591
102
      local_descriptors_node->entry_size = sizeof( pff_local_descriptor_branch_node_entry_type_32bit_t );
592
102
    }
593
108
  }
594
13.5k
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
595
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
596
13.5k
  {
597
13.5k
    if( local_descriptors_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
598
13.5k
    {
599
13.5k
      local_descriptors_node->entry_size = sizeof( pff_local_descriptor_leaf_node_entry_type_64bit_t );
600
13.5k
    }
601
29
    else
602
29
    {
603
29
      local_descriptors_node->entry_size = sizeof( pff_local_descriptor_branch_node_entry_type_64bit_t );
604
29
    }
605
13.5k
  }
606
/* TODO additional sanity checks */
607
608
13.7k
  if( local_descriptors_node->number_of_entries == 0 )
609
4
  {
610
4
    libcerror_error_set(
611
4
     error,
612
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
613
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
614
4
     "%s: invalid number of entries.",
615
4
     function );
616
617
/* TODO implement error tollerance */
618
4
    goto on_error;
619
4
  }
620
13.7k
  local_descriptors_node->entries_data_size = local_descriptors_node->number_of_entries * local_descriptors_node->entry_size;
621
622
13.7k
  if( local_descriptors_node->entries_data_size != ( data_size - header_data_size ) )
623
81
  {
624
81
    libcerror_error_set(
625
81
     error,
626
81
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
627
81
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
628
81
     "%s: mismatch in total size of the entries data and the size of the entries.",
629
81
     function );
630
631
/* TODO implement error tollerance */
632
81
    goto on_error;
633
81
  }
634
13.6k
  if( local_descriptors_node->entries_data_size > (size32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
635
0
  {
636
0
    libcerror_error_set(
637
0
     error,
638
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
639
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
640
0
     "%s: invalid local descriptors node - entries data size value exceeds maximum allocation size.",
641
0
     function );
642
643
0
    goto on_error;
644
0
  }
645
  /* Copy the entries data to the local descriptors node
646
   * to prevent loosing it when the data block is cached out.
647
   */
648
13.6k
  local_descriptors_node->entries_data = (uint8_t *) memory_allocate(
649
13.6k
                                                     sizeof( uint8_t ) * local_descriptors_node->entries_data_size );
650
651
13.6k
  if( local_descriptors_node->entries_data == NULL )
652
0
  {
653
0
    libcerror_error_set(
654
0
     error,
655
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
656
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
657
0
     "%s: unable to create entries data.",
658
0
     function );
659
660
0
    goto on_error;
661
0
  }
662
13.6k
  if( memory_copy(
663
13.6k
       local_descriptors_node->entries_data,
664
13.6k
       &( data[ header_data_size ] ),
665
13.6k
       local_descriptors_node->entries_data_size ) == NULL )
666
0
  {
667
0
    libcerror_error_set(
668
0
     error,
669
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
670
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
671
0
     "%s: unable to copy data array entry.",
672
0
     function );
673
674
0
    goto on_error;
675
0
  }
676
#if defined( HAVE_DEBUG_OUTPUT )
677
  if( libcnotify_verbose != 0 )
678
  {
679
    local_descriptors_node_entry_data = local_descriptors_node->entries_data;
680
681
    for( entry_index = 0;
682
         entry_index < local_descriptors_node->number_of_entries;
683
         entry_index++ )
684
    {
685
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
686
      {
687
        byte_stream_copy_to_uint32_little_endian(
688
         local_descriptors_node_entry_data,
689
         value_64bit );
690
691
        local_descriptors_node_entry_data += 4;
692
      }
693
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
694
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
695
      {
696
        byte_stream_copy_to_uint64_little_endian(
697
         local_descriptors_node_entry_data,
698
         value_64bit );
699
700
        local_descriptors_node_entry_data += 8;
701
      }
702
      libcnotify_printf(
703
       "%s: entry: %03d identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
704
       function,
705
       entry_index,
706
       value_64bit,
707
       value_64bit );
708
709
      if( local_descriptors_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
710
      {
711
        if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
712
        {
713
          byte_stream_copy_to_uint32_little_endian(
714
           local_descriptors_node_entry_data,
715
           value_64bit );
716
717
          local_descriptors_node_entry_data += 4;
718
        }
719
        else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
720
              || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
721
        {
722
          byte_stream_copy_to_uint64_little_endian(
723
           local_descriptors_node_entry_data,
724
           value_64bit );
725
726
          local_descriptors_node_entry_data += 8;
727
        }
728
        libcnotify_printf(
729
         "%s: entry: %03d data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
730
         function,
731
         entry_index,
732
         value_64bit,
733
         value_64bit );
734
      }
735
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
736
      {
737
        byte_stream_copy_to_uint32_little_endian(
738
         local_descriptors_node_entry_data,
739
         value_64bit );
740
741
        local_descriptors_node_entry_data += 4;
742
      }
743
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
744
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
745
      {
746
        byte_stream_copy_to_uint64_little_endian(
747
         local_descriptors_node_entry_data,
748
         value_64bit );
749
750
        local_descriptors_node_entry_data += 8;
751
      }
752
      if( local_descriptors_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
753
      {
754
        libcnotify_printf(
755
         "%s: entry: %03d local descriptors identifier\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
756
         function,
757
         entry_index,
758
         value_64bit,
759
         value_64bit );
760
      }
761
      else
762
      {
763
        libcnotify_printf(
764
         "%s: entry: %03d sub node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
765
         function,
766
         entry_index,
767
         value_64bit,
768
         value_64bit );
769
      }
770
    }
771
    libcnotify_printf(
772
     "\n" );
773
  }
774
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
775
776
13.6k
  return( 1 );
777
778
128
on_error:
779
128
  if( local_descriptors_node->entries_data != NULL )
780
0
  {
781
0
    memory_free(
782
0
     local_descriptors_node->entries_data );
783
784
0
    local_descriptors_node->entries_data = NULL;
785
0
  }
786
128
  local_descriptors_node->entries_data_size = 0;
787
788
128
  return( -1 );
789
13.6k
}
790
791
/* Reads a local descriptors node
792
 * Returns 1 if successful or -1 on error
793
 */
794
int libpff_local_descriptors_node_read_file_io_handle(
795
     libpff_local_descriptors_node_t *local_descriptors_node,
796
     libpff_io_handle_t *io_handle,
797
     libbfio_handle_t *file_io_handle,
798
     uint32_t descriptor_identifier,
799
     uint64_t data_identifier,
800
     off64_t node_offset,
801
     size32_t node_size,
802
     libcerror_error_t **error )
803
13.9k
{
804
13.9k
  libpff_data_block_t *data_block = NULL;
805
13.9k
  static char *function           = "libpff_local_descriptors_node_read_file_io_handle";
806
807
13.9k
  if( local_descriptors_node == NULL )
808
0
  {
809
0
    libcerror_error_set(
810
0
     error,
811
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
812
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
813
0
     "%s: invalid local descriptors node.",
814
0
     function );
815
816
0
    return( -1 );
817
0
  }
818
13.9k
  if( node_offset < 0 )
819
0
  {
820
0
    libcerror_error_set(
821
0
     error,
822
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
823
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
824
0
     "%s: invalid node offset value out of bounds.",
825
0
     function );
826
827
0
    return( -1 );
828
0
  }
829
13.9k
  if( node_size > (size32_t) SSIZE_MAX )
830
0
  {
831
0
    libcerror_error_set(
832
0
     error,
833
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
835
0
     "%s: node size value exceeds maximum.",
836
0
     function );
837
838
0
    return( -1 );
839
0
  }
840
13.9k
  if( libpff_data_block_initialize(
841
13.9k
       &data_block,
842
13.9k
       io_handle,
843
13.9k
       descriptor_identifier,
844
13.9k
       data_identifier,
845
13.9k
       error ) != 1 )
846
0
  {
847
0
    libcerror_error_set(
848
0
     error,
849
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
850
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
851
0
     "%s: unable to create data block.",
852
0
     function );
853
854
0
    goto on_error;
855
0
  }
856
13.9k
  if( libpff_data_block_read_file_io_handle(
857
13.9k
       data_block,
858
13.9k
       file_io_handle,
859
13.9k
       node_offset,
860
13.9k
       node_size,
861
13.9k
       io_handle->file_type,
862
13.9k
       error ) != 1 )
863
142
  {
864
142
    libcerror_error_set(
865
142
     error,
866
142
     LIBCERROR_ERROR_DOMAIN_IO,
867
142
     LIBCERROR_IO_ERROR_READ_FAILED,
868
142
     "%s: unable to read data block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
869
142
     function,
870
142
     node_offset,
871
142
     node_offset );
872
873
142
    goto on_error;
874
142
  }
875
13.7k
  if( libpff_local_descriptors_node_read_data(
876
13.7k
       local_descriptors_node,
877
13.7k
       io_handle,
878
13.7k
       data_block->data,
879
13.7k
       data_block->uncompressed_data_size,
880
13.7k
       error ) != 1 )
881
158
  {
882
158
    libcerror_error_set(
883
158
     error,
884
158
     LIBCERROR_ERROR_DOMAIN_IO,
885
158
     LIBCERROR_IO_ERROR_READ_FAILED,
886
158
     "%s: unable to read local descriptors node.",
887
158
     function );
888
889
158
    goto on_error;
890
158
  }
891
13.6k
  if( libpff_data_block_free(
892
13.6k
       &data_block,
893
13.6k
       error ) != 1 )
894
0
  {
895
0
    libcerror_error_set(
896
0
     error,
897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
899
0
     "%s: unable to free data block.",
900
0
     function );
901
902
0
    goto on_error;
903
0
  }
904
13.6k
  return( 1 );
905
906
300
on_error:
907
300
  if( local_descriptors_node->entries_data != NULL )
908
0
  {
909
0
    memory_free(
910
0
     local_descriptors_node->entries_data );
911
912
0
    local_descriptors_node->entries_data = NULL;
913
0
  }
914
300
  local_descriptors_node->entries_data_size = 0;
915
916
300
  if( data_block != NULL )
917
300
  {
918
300
    libpff_data_block_free(
919
300
     &data_block,
920
     NULL );
921
300
  }
922
300
  return( -1 );
923
13.6k
}
924