Coverage Report

Created: 2024-10-02 06:58

/src/libpff/libpff/libpff_descriptor_data_stream.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The descriptor data stream 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 <memory.h>
24
#include <types.h>
25
26
#include "libpff_data_block.h"
27
#include "libpff_definitions.h"
28
#include "libpff_descriptor_data_stream.h"
29
#include "libpff_libcerror.h"
30
#include "libpff_libfcache.h"
31
#include "libpff_libfdata.h"
32
#include "libpff_unused.h"
33
34
/* Creates a data handle
35
 * Make sure the value data_handle is referencing, is set to NULL
36
 * Returns 1 if successful or -1 on error
37
 */
38
int libpff_descriptor_data_stream_data_handle_initialize(
39
     libpff_descriptor_data_stream_data_handle_t **data_handle,
40
     libcerror_error_t **error )
41
1.61k
{
42
1.61k
  static char *function = "libpff_descriptor_data_stream_data_handle_initialize";
43
44
1.61k
  if( data_handle == NULL )
45
0
  {
46
0
    libcerror_error_set(
47
0
     error,
48
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50
0
     "%s: invalid data handle.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
1.61k
  if( *data_handle != NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61
0
     "%s: invalid data handle value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
1.61k
  *data_handle = memory_allocate_structure(
67
1.61k
                  libpff_descriptor_data_stream_data_handle_t );
68
69
1.61k
  if( *data_handle == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
74
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
75
0
     "%s: unable to create data handle.",
76
0
     function );
77
78
0
    goto on_error;
79
0
  }
80
1.61k
  if( memory_set(
81
1.61k
       *data_handle,
82
1.61k
       0,
83
1.61k
       sizeof( libpff_descriptor_data_stream_data_handle_t ) ) == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
88
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
89
0
     "%s: unable to clear data handle.",
90
0
     function );
91
92
0
    goto on_error;
93
0
  }
94
1.61k
  return( 1 );
95
96
0
on_error:
97
0
  if( *data_handle != NULL )
98
0
  {
99
0
    memory_free(
100
0
     *data_handle );
101
102
0
    *data_handle = NULL;
103
0
  }
104
0
  return( -1 );
105
1.61k
}
106
107
/* Frees a data handle
108
 * Returns 1 if successful or -1 on error
109
 */
110
int libpff_descriptor_data_stream_data_handle_free(
111
     libpff_descriptor_data_stream_data_handle_t **data_handle,
112
     libcerror_error_t **error )
113
1.61k
{
114
1.61k
  static char *function = "libpff_descriptor_data_stream_data_handle_free";
115
1.61k
  int result            = 1;
116
117
1.61k
  if( data_handle == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
122
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
123
0
     "%s: invalid data handle.",
124
0
     function );
125
126
0
    return( -1 );
127
0
  }
128
1.61k
  if( *data_handle != NULL )
129
1.61k
  {
130
1.61k
    if( ( *data_handle )->flags == LIBPFF_DESCRIPTOR_DATA_STREAM_DATA_HANDLE_FLAG_MANAGED )
131
0
    {
132
0
      if( ( *data_handle )->descriptor_data_cache != NULL )
133
0
      {
134
0
        if( libfcache_cache_free(
135
0
             &( ( *data_handle )->descriptor_data_cache ),
136
0
             error ) != 1 )
137
0
        {
138
0
          libcerror_error_set(
139
0
           error,
140
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
141
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
142
0
           "%s: unable to free descriptor data cache.",
143
0
           function );
144
145
0
          result = -1;
146
0
        }
147
0
      }
148
0
      if( ( *data_handle )->descriptor_data_list != NULL )
149
0
      {
150
0
        if( libfdata_list_free(
151
0
             &( ( *data_handle )->descriptor_data_list ),
152
0
             error ) != 1 )
153
0
        {
154
0
          libcerror_error_set(
155
0
           error,
156
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
157
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
158
0
           "%s: unable to free descriptor data list.",
159
0
           function );
160
161
0
          result = -1;
162
0
        }
163
0
      }
164
0
    }
165
1.61k
    memory_free(
166
1.61k
     *data_handle );
167
168
1.61k
    *data_handle = NULL;
169
1.61k
  }
170
1.61k
  return( result );
171
1.61k
}
172
173
/* Clones (duplicates) the data handle
174
 * Returns 1 if successful or -1 on error
175
 */
176
int libpff_descriptor_data_stream_data_handle_clone(
177
     libpff_descriptor_data_stream_data_handle_t **destination_data_handle,
178
     libpff_descriptor_data_stream_data_handle_t *source_data_handle,
179
     libcerror_error_t **error )
180
0
{
181
0
  static char *function = "libpff_descriptor_data_stream_data_handle_clone";
182
183
0
  if( destination_data_handle == NULL )
184
0
  {
185
0
    libcerror_error_set(
186
0
     error,
187
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
189
0
     "%s: invalid destination data handle.",
190
0
     function );
191
192
0
    return( -1 );
193
0
  }
194
0
  if( *destination_data_handle != NULL )
195
0
  {
196
0
    libcerror_error_set(
197
0
     error,
198
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
199
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
200
0
     "%s: invalid destination data handle value already set.",
201
0
     function );
202
203
0
    return( -1 );
204
0
  }
205
0
  if( source_data_handle == NULL )
206
0
  {
207
0
    *destination_data_handle = NULL;
208
209
0
    return( 1 );
210
0
  }
211
0
  *destination_data_handle = memory_allocate_structure(
212
0
                              libpff_descriptor_data_stream_data_handle_t );
213
214
0
  if( *destination_data_handle == NULL )
215
0
  {
216
0
    libcerror_error_set(
217
0
     error,
218
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
219
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
220
0
     "%s: unable to create destination data handle.",
221
0
     function );
222
223
0
    goto on_error;
224
0
  }
225
0
  if( memory_copy(
226
0
       *destination_data_handle,
227
0
       source_data_handle,
228
0
       sizeof( libpff_descriptor_data_stream_data_handle_t ) ) == NULL )
229
0
  {
230
0
    libcerror_error_set(
231
0
     error,
232
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
233
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
234
0
     "%s: unable to copy source to destination data handle.",
235
0
     function );
236
237
0
    goto on_error;
238
0
  }
239
/* TODO clone list and cache ? */
240
0
  return( 1 );
241
242
0
on_error:
243
0
  if( *destination_data_handle != NULL )
244
0
  {
245
0
    memory_free(
246
0
     *destination_data_handle );
247
248
0
    *destination_data_handle = NULL;
249
0
  }
250
0
  return( -1 );
251
0
}
252
253
/* Reads data from the current offset into a buffer
254
 * Callback for the descriptor data stream
255
 * Returns the number of bytes read or -1 on error
256
 */
257
ssize_t libpff_descriptor_data_stream_data_handle_read_segment_data(
258
         libpff_descriptor_data_stream_data_handle_t *data_handle,
259
         intptr_t *file_io_handle,
260
         int segment_index,
261
         int segment_file_index LIBPFF_ATTRIBUTE_UNUSED,
262
         uint8_t *segment_data,
263
         size_t segment_data_size,
264
         uint32_t segment_flags LIBPFF_ATTRIBUTE_UNUSED,
265
         uint8_t read_flags,
266
         libcerror_error_t **error )
267
927
{
268
927
  libpff_data_block_t *data_block = NULL;
269
927
  static char *function           = "libpff_descriptor_data_stream_data_handle_read_segment_data";
270
927
  off64_t element_data_offset     = 0;
271
927
  ssize_t read_count              = 0;
272
927
  int element_index               = 0;
273
274
927
  LIBPFF_UNREFERENCED_PARAMETER( segment_file_index )
275
927
  LIBPFF_UNREFERENCED_PARAMETER( segment_flags )
276
277
927
  if( data_handle == NULL )
278
0
  {
279
0
    libcerror_error_set(
280
0
     error,
281
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
282
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
283
0
     "%s: invalid data handle.",
284
0
     function );
285
286
0
    return( -1 );
287
0
  }
288
927
  if( segment_data == NULL )
289
0
  {
290
0
    libcerror_error_set(
291
0
     error,
292
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
293
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
294
0
     "%s: invalid segment data.",
295
0
     function );
296
297
0
    return( -1 );
298
0
  }
299
927
  if( segment_data_size > (size_t) SSIZE_MAX )
300
0
  {
301
0
    libcerror_error_set(
302
0
     error,
303
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
305
0
     "%s: invalid segment data size value exceeds maximum.",
306
0
     function );
307
308
0
    return( -1 );
309
0
  }
310
927
  if( libfdata_list_get_element_value_at_offset(
311
927
       data_handle->descriptor_data_list,
312
927
       file_io_handle,
313
927
       (libfdata_cache_t *) data_handle->descriptor_data_cache,
314
927
       data_handle->current_offset,
315
927
       &element_index,
316
927
       &element_data_offset,
317
927
       (intptr_t **) &data_block,
318
927
       read_flags,
319
927
       error ) != 1 )
320
0
  {
321
0
    libcerror_error_set(
322
0
     error,
323
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
325
0
     "%s: unable to retrieve data block: %d.",
326
0
     function,
327
0
     segment_index );
328
329
0
    return( -1 );
330
0
  }
331
927
  if( element_index != segment_index )
332
0
  {
333
0
    libcerror_error_set(
334
0
     error,
335
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
336
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
337
0
     "%s: element index value out of bounds.",
338
0
     function );
339
340
0
    return( -1 );
341
0
  }
342
927
  if( data_block == NULL )
343
0
  {
344
0
    libcerror_error_set(
345
0
     error,
346
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
347
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
348
0
     "%s: missing data block: %d.",
349
0
     function,
350
0
     segment_index );
351
352
0
    return( -1 );
353
0
  }
354
927
  if( ( element_data_offset < 0 )
355
927
   || ( element_data_offset >= (off64_t) data_block->uncompressed_data_size ) )
356
0
  {
357
0
    libcerror_error_set(
358
0
     error,
359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
361
0
     "%s: invalid element data offset value out of bounds.",
362
0
     function );
363
364
0
    return( -1 );
365
0
  }
366
927
  if( ( element_data_offset + segment_data_size ) > (off64_t) data_block->uncompressed_data_size )
367
0
  {
368
0
    read_count = (ssize_t) ( data_block->uncompressed_data_size - element_data_offset );
369
0
  }
370
927
  else
371
927
  {
372
927
    read_count = (ssize_t) segment_data_size;
373
927
  }
374
927
  if( memory_copy(
375
927
       segment_data,
376
927
       &( data_block->data[ element_data_offset ] ),
377
927
       (size_t) read_count ) == NULL )
378
0
  {
379
0
    libcerror_error_set(
380
0
     error,
381
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
382
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
383
0
     "%s: unable to copy data block data.",
384
0
     function );
385
386
0
    return( -1 );
387
0
  }
388
927
  return( read_count );
389
927
}
390
391
/* Seeks a certain offset of the data
392
 * Callback for the descriptor data stream
393
 * Returns the offset if seek is successful or -1 on error
394
 */
395
off64_t libpff_descriptor_data_stream_data_handle_seek_segment_offset(
396
         libpff_descriptor_data_stream_data_handle_t *data_handle,
397
         intptr_t *file_io_handle LIBPFF_ATTRIBUTE_UNUSED,
398
         int segment_index LIBPFF_ATTRIBUTE_UNUSED,
399
         int segment_file_index LIBPFF_ATTRIBUTE_UNUSED,
400
         off64_t segment_offset,
401
         libcerror_error_t **error )
402
927
{
403
927
  static char *function = "libpff_descriptor_data_stream_data_handle_seek_segment_offset";
404
405
927
  LIBPFF_UNREFERENCED_PARAMETER( file_io_handle )
406
927
  LIBPFF_UNREFERENCED_PARAMETER( segment_index )
407
927
  LIBPFF_UNREFERENCED_PARAMETER( segment_file_index )
408
409
927
  if( data_handle == NULL )
410
0
  {
411
0
    libcerror_error_set(
412
0
     error,
413
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
415
0
     "%s: invalid data handle.",
416
0
     function );
417
418
0
    return( -1 );
419
0
  }
420
927
  if( segment_offset < 0 )
421
0
  {
422
0
    libcerror_error_set(
423
0
     error,
424
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
425
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
426
0
     "%s: invalid segment offset value out of bounds.",
427
0
     function );
428
429
0
    return( -1 );
430
0
  }
431
927
  data_handle->current_offset = segment_offset;
432
433
927
  return( segment_offset );
434
927
}
435
436
/* Creates a descriptor data stream
437
 * Make sure the value descriptor_data_stream is referencing, is set to NULL
438
 * Returns 1 if successful or -1 on error
439
 */
440
int libpff_descriptor_data_stream_initialize(
441
     libfdata_stream_t **descriptor_data_stream,
442
     libfdata_list_t *descriptor_data_list,
443
     libfcache_cache_t *descriptor_data_cache,
444
     uint8_t flags,
445
     libcerror_error_t **error )
446
1.61k
{
447
1.61k
  libpff_descriptor_data_stream_data_handle_t *data_handle = NULL;
448
1.61k
  static char *function                                    = "libpff_descriptor_data_stream_initialize";
449
1.61k
  off64_t segment_offset                                   = 0;
450
1.61k
  size64_t segment_size                                    = 0;
451
1.61k
  int element_index                                        = 0;
452
1.61k
  int number_of_elements                                   = 0;
453
1.61k
  int segment_index                                        = 0;
454
455
1.61k
  if( descriptor_data_stream == NULL )
456
0
  {
457
0
    libcerror_error_set(
458
0
     error,
459
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
460
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
461
0
     "%s: invalid descriptor data stream.",
462
0
     function );
463
464
0
    return( -1 );
465
0
  }
466
1.61k
  if( descriptor_data_list == NULL )
467
0
  {
468
0
    libcerror_error_set(
469
0
     error,
470
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
471
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
472
0
     "%s: invalid descriptor data list.",
473
0
     function );
474
475
0
    return( -1 );
476
0
  }
477
1.61k
  if( descriptor_data_cache == NULL )
478
0
  {
479
0
    libcerror_error_set(
480
0
     error,
481
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
482
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
483
0
     "%s: invalid descriptor data cache.",
484
0
     function );
485
486
0
    return( -1 );
487
0
  }
488
1.61k
  if( libpff_descriptor_data_stream_data_handle_initialize(
489
1.61k
       &data_handle,
490
1.61k
       error ) != 1 )
491
0
  {
492
0
    libcerror_error_set(
493
0
     error,
494
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
496
0
     "%s: unable to create data handle.",
497
0
     function );
498
499
0
    goto on_error;
500
0
  }
501
1.61k
  if( data_handle == NULL )
502
0
  {
503
0
    libcerror_error_set(
504
0
     error,
505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
506
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
507
0
     "%s: missing data handle.",
508
0
     function );
509
510
0
    goto on_error;
511
0
  }
512
1.61k
  if( libfdata_stream_initialize(
513
1.61k
       descriptor_data_stream,
514
1.61k
       (intptr_t *) data_handle,
515
1.61k
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_descriptor_data_stream_data_handle_free,
516
1.61k
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libpff_descriptor_data_stream_data_handle_clone,
517
1.61k
       NULL,
518
1.61k
       (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libpff_descriptor_data_stream_data_handle_read_segment_data,
519
1.61k
       NULL,
520
1.61k
       (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libpff_descriptor_data_stream_data_handle_seek_segment_offset,
521
1.61k
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
522
1.61k
       error ) != 1 )
523
0
  {
524
0
    libcerror_error_set(
525
0
     error,
526
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
527
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
528
0
     "%s: unable to create stream.",
529
0
     function );
530
531
0
    goto on_error;
532
0
  }
533
1.61k
  if( libfdata_list_get_number_of_elements(
534
1.61k
       descriptor_data_list,
535
1.61k
       &number_of_elements,
536
1.61k
       error ) != 1 )
537
0
  {
538
0
    libcerror_error_set(
539
0
     error,
540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
541
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
542
0
     "%s: unable to retrieve number of descriptor data list elements.",
543
0
     function );
544
545
0
    data_handle = NULL;
546
547
0
    goto on_error;
548
0
  }
549
1.61k
  for( element_index = 0;
550
3.20k
       element_index < number_of_elements;
551
1.61k
       element_index++ )
552
1.58k
  {
553
1.58k
    if( libfdata_list_get_mapped_size_by_index(
554
1.58k
         descriptor_data_list,
555
1.58k
         element_index,
556
1.58k
         &segment_size,
557
1.58k
         error ) != 1 )
558
0
    {
559
0
      libcerror_error_set(
560
0
       error,
561
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
563
0
       "%s: unable to retrieve descriptor data list element: %d mapped size.",
564
0
       function,
565
0
       element_index );
566
567
0
      data_handle = NULL;
568
569
0
      goto on_error;
570
0
    }
571
1.58k
    if( libfdata_stream_append_segment(
572
1.58k
         *descriptor_data_stream,
573
1.58k
         &segment_index,
574
1.58k
         0,
575
1.58k
         segment_offset,
576
1.58k
         segment_size,
577
1.58k
         0,
578
1.58k
         error ) != 1 )
579
0
    {
580
0
      libcerror_error_set(
581
0
       error,
582
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
583
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
584
0
       "%s: unable to append descriptor data stream segment: %d.",
585
0
       function,
586
0
       element_index );
587
588
0
      data_handle = NULL;
589
590
0
      goto on_error;
591
0
    }
592
1.58k
    segment_offset += segment_size;
593
1.58k
  }
594
1.61k
  data_handle->descriptor_data_list  = descriptor_data_list;
595
1.61k
  data_handle->descriptor_data_cache = descriptor_data_cache;
596
1.61k
  data_handle->flags                 = flags;
597
598
1.61k
  return( 1 );
599
600
0
on_error:
601
0
  if( *descriptor_data_stream != NULL )
602
0
  {
603
0
    libfdata_stream_free(
604
0
     descriptor_data_stream,
605
0
     NULL );
606
0
  }
607
0
  if( data_handle != NULL )
608
0
  {
609
0
    libpff_descriptor_data_stream_data_handle_free(
610
0
     &data_handle,
611
0
     NULL );
612
0
  }
613
0
  return( -1 );
614
1.61k
}
615