Coverage Report

Created: 2026-10-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libewf/libewf/libewf_chunk_group.c
Line
Count
Source
1
/*
2
 * Chunk group functions
3
 *
4
 * Copyright (C) 2006-2026, 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 "libewf_chunk_data.h"
28
#include "libewf_chunk_group.h"
29
#include "libewf_definitions.h"
30
#include "libewf_io_handle.h"
31
#include "libewf_libcerror.h"
32
#include "libewf_libcnotify.h"
33
#include "libewf_libfcache.h"
34
#include "libewf_libfdata.h"
35
#include "libewf_section.h"
36
#include "libewf_section_descriptor.h"
37
#include "libewf_unused.h"
38
39
#include "ewf_table.h"
40
41
/* Creates a chunk group
42
 * Make sure the value chunk_group is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libewf_chunk_group_initialize(
46
     libewf_chunk_group_t **chunk_group,
47
     libewf_io_handle_t *io_handle,
48
     libcerror_error_t **error )
49
0
{
50
0
  static char *function = "libewf_chunk_group_initialize";
51
52
0
  if( chunk_group == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid chunk group.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
0
  if( *chunk_group != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid chunk group value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
0
  if( io_handle == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
79
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
80
0
     "%s: invalid IO handle.",
81
0
     function );
82
83
0
    return( -1 );
84
0
  }
85
0
  *chunk_group = memory_allocate_structure(
86
0
                  libewf_chunk_group_t );
87
88
0
  if( *chunk_group == 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 chunk group.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
0
  if( memory_set(
100
0
       *chunk_group,
101
0
       0,
102
0
       sizeof( libewf_chunk_group_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 chunk group.",
109
0
     function );
110
111
0
    memory_free(
112
0
     *chunk_group );
113
114
0
    *chunk_group = NULL;
115
116
0
    return( -1 );
117
0
  }
118
0
  if( libfdata_list_initialize(
119
0
       &( ( *chunk_group )->chunks_list ),
120
0
       (intptr_t *) io_handle,
121
0
       NULL,
122
0
       NULL,
123
0
       (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libewf_chunk_data_read_element_data,
124
0
       NULL,
125
0
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
126
0
       error ) != 1 )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
131
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
132
0
     "%s: unable to create chunks list.",
133
0
     function );
134
135
0
    goto on_error;
136
0
  }
137
0
  return( 1 );
138
139
0
on_error:
140
0
  if( *chunk_group != NULL )
141
0
  {
142
0
    memory_free(
143
0
     *chunk_group );
144
145
0
    *chunk_group = NULL;
146
0
  }
147
0
  return( -1 );
148
0
}
149
150
/* Frees a chunk group
151
 * Returns 1 if successful or -1 on error
152
 */
153
int libewf_chunk_group_free(
154
     libewf_chunk_group_t **chunk_group,
155
     libcerror_error_t **error )
156
0
{
157
0
        static char *function = "libewf_chunk_group_free";
158
0
  int result            = 1;
159
160
0
  if( chunk_group == 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 chunk group.",
167
0
     function );
168
169
0
    return( -1 );
170
0
  }
171
0
  if( *chunk_group != NULL )
172
0
  {
173
0
    if( libfdata_list_free(
174
0
         &( ( *chunk_group )->chunks_list ),
175
0
         error ) != 1 )
176
0
    {
177
0
      libcerror_error_set(
178
0
       error,
179
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
180
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
181
0
       "%s: unable to free chunks list.",
182
0
       function );
183
184
0
      result = -1;
185
0
    }
186
0
    memory_free(
187
0
     *chunk_group );
188
189
0
    *chunk_group = NULL;
190
0
  }
191
0
  return( result );
192
0
}
193
194
/* Clones the chunk group
195
 * Returns 1 if successful or -1 on error
196
 */
197
int libewf_chunk_group_clone(
198
     libewf_chunk_group_t **destination_chunk_group,
199
     libewf_chunk_group_t *source_chunk_group,
200
     libcerror_error_t **error )
201
0
{
202
0
  static char *function = "libewf_chunk_group_clone";
203
204
0
  if( destination_chunk_group == NULL )
205
0
  {
206
0
    libcerror_error_set(
207
0
     error,
208
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
209
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
210
0
     "%s: invalid destination chunk group.",
211
0
     function );
212
213
0
    return( -1 );
214
0
  }
215
0
  if( *destination_chunk_group != NULL )
216
0
  {
217
0
    libcerror_error_set(
218
0
     error,
219
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
220
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
221
0
     "%s: invalid destination chunk group already set.",
222
0
     function );
223
224
0
    return( -1 );
225
0
  }
226
0
  if( source_chunk_group == NULL )
227
0
  {
228
0
    *destination_chunk_group = NULL;
229
230
0
    return( 1 );
231
0
  }
232
0
  *destination_chunk_group = memory_allocate_structure(
233
0
                        libewf_chunk_group_t );
234
235
0
  if( *destination_chunk_group == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
240
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
241
0
     "%s: unable to create destination chunk group.",
242
0
     function );
243
244
0
    goto on_error;
245
0
  }
246
0
  if( memory_copy(
247
0
       *destination_chunk_group,
248
0
       source_chunk_group,
249
0
       sizeof( libewf_chunk_group_t ) ) == NULL )
250
0
  {
251
0
    libcerror_error_set(
252
0
     error,
253
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
254
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
255
0
     "%s: unable to copy source to destination chunk group.",
256
0
     function );
257
258
0
    memory_free(
259
0
     *destination_chunk_group );
260
261
0
    *destination_chunk_group = NULL;
262
263
0
    return( -1 );
264
0
  }
265
0
  ( *destination_chunk_group )->chunks_list = NULL;
266
267
/* TODO clone chunks_list */
268
269
0
  return( 1 );
270
271
0
on_error:
272
0
  if( *destination_chunk_group != NULL )
273
0
  {
274
0
    memory_free(
275
0
     *destination_chunk_group );
276
277
0
    *destination_chunk_group = NULL;
278
0
  }
279
0
  return( -1 );
280
0
}
281
282
/* Empties a chunk group
283
 * Returns 1 if successful or -1 on error
284
 */
285
int libewf_chunk_group_empty(
286
     libewf_chunk_group_t *chunk_group,
287
     libcerror_error_t **error )
288
0
{
289
0
        static char *function = "libewf_chunk_group_empty";
290
291
0
  if( chunk_group == NULL )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
296
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
297
0
     "%s: invalid chunk group.",
298
0
     function );
299
300
0
    return( -1 );
301
0
  }
302
0
  if( libfdata_list_empty(
303
0
       chunk_group->chunks_list,
304
0
       error ) != 1 )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
309
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
310
0
     "%s: unable to empty chunks list.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
0
  return( 1 );
316
0
}
317
318
/* Fills the chunks list from the EWF version 1 sector table entries
319
 * Returns 1 if successful or -1 on error
320
 */
321
int libewf_chunk_group_fill_v1(
322
     libewf_chunk_group_t *chunk_group,
323
     uint64_t chunk_index,
324
     size32_t chunk_size,
325
     int file_io_pool_entry,
326
     libewf_section_descriptor_t *table_section,
327
     off64_t base_offset,
328
     uint32_t number_of_entries,
329
     const uint8_t *table_entries_data,
330
     size_t table_entries_data_size,
331
     uint8_t tainted,
332
     libcerror_error_t **error )
333
0
{
334
0
  static char *function          = "libewf_chunk_group_fill_v1";
335
0
  size_t data_offset             = 0;
336
0
  off64_t chunk_data_end_offset  = 0;
337
0
  off64_t last_chunk_data_offset = 0;
338
0
  off64_t last_chunk_data_size   = 0;
339
0
  uint32_t chunk_data_size       = 0;
340
0
  uint32_t current_offset        = 0;
341
0
  uint32_t next_offset           = 0;
342
0
  uint32_t range_flags           = 0;
343
0
  uint32_t stored_offset         = 0;
344
0
  uint32_t table_entry_index     = 0;
345
0
  uint8_t corrupted              = 0;
346
0
  uint8_t is_compressed          = 0;
347
0
  uint8_t overflow               = 0;
348
0
  int element_index              = 0;
349
350
0
  if( chunk_group == NULL )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
356
0
     "%s: invalid chunk group.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
  if( table_section == NULL )
362
0
  {
363
0
    libcerror_error_set(
364
0
     error,
365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
367
0
     "%s: invalid table section.",
368
0
     function );
369
370
0
    return( -1 );
371
0
  }
372
0
  if( base_offset < 0 )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
378
0
     "%s: invalid base offset.",
379
0
     function );
380
381
0
    return( -1 );
382
0
  }
383
0
  if( table_entries_data == NULL )
384
0
  {
385
0
    libcerror_error_set(
386
0
     error,
387
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
389
0
     "%s: invalid table entries data.",
390
0
     function );
391
392
0
    return( -1 );
393
0
  }
394
0
  if( table_entries_data_size > (size_t) SSIZE_MAX )
395
0
  {
396
0
    libcerror_error_set(
397
0
     error,
398
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
399
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
400
0
     "%s: invalid table entries data size value exceeds maximum.",
401
0
     function );
402
403
0
    return( -1 );
404
0
  }
405
0
  byte_stream_copy_to_uint32_little_endian(
406
0
   &( table_entries_data[ data_offset ] ),
407
0
   stored_offset );
408
409
0
  data_offset += sizeof( ewf_table_entry_v1_t );
410
411
0
  for( table_entry_index = 0;
412
0
       table_entry_index < ( number_of_entries - 1 );
413
0
       table_entry_index++ )
414
0
  {
415
0
    if( overflow == 0 )
416
0
    {
417
0
      is_compressed  = (uint8_t) ( stored_offset >> 31 );
418
0
      current_offset = stored_offset & 0x7fffffffUL;
419
0
    }
420
0
    else
421
0
    {
422
0
      current_offset = stored_offset;
423
0
    }
424
0
    byte_stream_copy_to_uint32_little_endian(
425
0
     &( table_entries_data[ data_offset ] ),
426
0
     stored_offset );
427
428
0
    data_offset += sizeof( ewf_table_entry_v1_t );
429
430
0
    if( overflow == 0 )
431
0
    {
432
0
      next_offset = stored_offset & 0x7fffffffUL;
433
0
    }
434
0
    else
435
0
    {
436
0
      next_offset = stored_offset;
437
0
    }
438
0
    corrupted = 0;
439
440
    /* This is to compensate for the crappy > 2 GiB segment file solution in EnCase 6.7
441
     */
442
0
    if( next_offset < current_offset )
443
0
    {
444
0
      if( stored_offset < current_offset )
445
0
      {
446
#if defined( HAVE_DEBUG_OUTPUT )
447
        if( libcnotify_verbose != 0 )
448
        {
449
          libcnotify_printf(
450
           "%s: entry: %" PRIu32 " offset: %" PRIu32 " larger than stored offset: %" PRIu32 ".\n",
451
           function,
452
           table_entry_index,
453
           current_offset,
454
           stored_offset );
455
        }
456
#endif
457
0
        corrupted = 1;
458
0
      }
459
#if defined( HAVE_DEBUG_OUTPUT )
460
      else if( libcnotify_verbose != 0 )
461
      {
462
        libcnotify_printf(
463
         "%s: entry: %" PRIu32 " offset: %" PRIu32 " larger than next offset: %" PRIu32 ".\n",
464
         function,
465
         table_entry_index,
466
         current_offset,
467
         next_offset );
468
      }
469
#endif
470
0
      chunk_data_size = stored_offset - current_offset;
471
0
    }
472
0
    else
473
0
    {
474
0
      chunk_data_size = next_offset - current_offset;
475
0
    }
476
0
    if( chunk_data_size == 0 )
477
0
    {
478
0
      if( libcnotify_verbose != 0 )
479
0
      {
480
0
        libcnotify_printf(
481
0
         "%s: invalid entry: %" PRIu32 " size value is zero.\n",
482
0
         function,
483
0
         table_entry_index );
484
0
      }
485
0
      corrupted = 1;
486
0
    }
487
0
    if( chunk_data_size > (uint32_t) INT32_MAX )
488
0
    {
489
0
      if( libcnotify_verbose != 0 )
490
0
      {
491
0
        libcnotify_printf(
492
0
         "%s: invalid entry: %" PRIu32 " size value exceeds maximum.\n",
493
0
         function,
494
0
         table_entry_index );
495
0
      }
496
0
      corrupted = 1;
497
0
    }
498
0
    if( is_compressed != 0 )
499
0
    {
500
0
      range_flags = LIBEWF_RANGE_FLAG_IS_COMPRESSED;
501
0
    }
502
0
    else
503
0
    {
504
0
      range_flags = LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
505
0
    }
506
0
    if( corrupted != 0 )
507
0
    {
508
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
509
0
    }
510
0
    if( tainted != 0 )
511
0
    {
512
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_TAINTED;
513
0
    }
514
#if defined( HAVE_DEBUG_OUTPUT )
515
    if( libcnotify_verbose != 0 )
516
    {
517
      libcnotify_printf(
518
       "%s: table entry: %05" PRIu32 " chunk\t\t\t: %" PRIu64 "\n",
519
       function,
520
       table_entry_index,
521
       chunk_index );
522
523
      libcnotify_printf(
524
       "%s: table entry: %05" PRIu32 " base offset\t\t: 0x%08" PRIx64 "\n",
525
       function,
526
       table_entry_index,
527
       base_offset );
528
529
      libcnotify_printf(
530
       "%s: table entry: %05" PRIu32 " chunk data offset\t: %" PRIu32 " (0x%08" PRIx32 ") (file offset: 0x%08" PRIx64 ")\n",
531
       function,
532
       table_entry_index,
533
       current_offset,
534
       current_offset,
535
       base_offset + current_offset );
536
537
      libcnotify_printf(
538
       "%s: table entry: %05" PRIu32 " chunk data size\t\t: %" PRIu32 "\n",
539
       function,
540
       table_entry_index,
541
       chunk_data_size );
542
543
      libcnotify_printf(
544
       "%s: table entry: %05" PRIu32 " chunk data flags:\n",
545
       function,
546
       table_entry_index );
547
548
      if( is_compressed != 0 )
549
      {
550
        libcnotify_printf(
551
         "\tIs compressed\n" );
552
      }
553
      else
554
      {
555
        libcnotify_printf(
556
         "\tHas checksum\n" );
557
      }
558
      if( corrupted != 0 )
559
      {
560
        libcnotify_printf(
561
         "\tIs corrupted\n" );
562
      }
563
      else if( tainted != 0 )
564
      {
565
        libcnotify_printf(
566
         "\tIs tainted\n" );
567
      }
568
      libcnotify_printf(
569
       "\n" );
570
    }
571
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
572
573
0
    chunk_index++;
574
575
0
    if( libfdata_list_append_element_with_mapped_size(
576
0
         chunk_group->chunks_list,
577
0
         &element_index,
578
0
         file_io_pool_entry,
579
0
         base_offset + current_offset,
580
0
         (size64_t) chunk_data_size,
581
0
         range_flags,
582
0
         chunk_size,
583
0
         error ) != 1 )
584
0
    {
585
0
      libcerror_error_set(
586
0
       error,
587
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
588
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
589
0
       "%s: unable to append element: %" PRIu32 " with mapped size to chunks list.",
590
0
       function,
591
0
       table_entry_index );
592
593
0
      return( -1 );
594
0
    }
595
    /* This is to compensate for the crappy > 2 GiB segment file solution in EnCase 6.7
596
     */
597
0
    if( ( overflow == 0 )
598
0
     && ( ( current_offset + chunk_data_size ) > (uint32_t) INT32_MAX ) )
599
0
    {
600
#if defined( HAVE_DEBUG_OUTPUT )
601
      if( libcnotify_verbose != 0 )
602
      {
603
        libcnotify_printf(
604
         "%s: entry: %" PRIu64 " offset overflow at: %" PRIu32 ".\n",
605
         function,
606
         table_entry_index,
607
         current_offset );
608
      }
609
#endif
610
0
      overflow      = 1;
611
0
      is_compressed = 0;
612
0
    }
613
0
  }
614
0
  if( overflow == 0 )
615
0
  {
616
0
    is_compressed  = (uint8_t) ( stored_offset >> 31 );
617
0
    current_offset = stored_offset & 0x7fffffffUL;
618
0
  }
619
0
  else
620
0
  {
621
0
    current_offset = stored_offset;
622
0
  }
623
0
  corrupted = 0;
624
625
  /* There is no indication how large the last chunk is.
626
   * The only thing known is where it starts.
627
   * However it can be determined using the offset of the next section.
628
   * The size of the last chunk is determined by subtracting the last offset from the offset of the next section.
629
   *
630
   * The offset of the next section is either table_section->end_offset for original EWF and EWF-S01
631
   * or table_section->start_offset for other types of EWF
632
   */
633
0
  last_chunk_data_offset = (off64_t) base_offset + current_offset;
634
635
0
  if( last_chunk_data_offset > (off64_t) INT64_MAX )
636
0
  {
637
0
    libcerror_error_set(
638
0
     error,
639
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
640
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
641
0
     "%s: invalid last entry: %" PRIu32 " offset value exceeds maximum.",
642
0
     function,
643
0
     table_entry_index );
644
645
0
    return( -1 );
646
0
  }
647
  /* A table2 section where the chunk data is stored 2 sections before
648
   */
649
0
  if( ( table_section->type_string_length == 6 )
650
0
   && ( memory_compare(
651
0
         (void *) table_section->type_string,
652
0
         (void *) "table2",
653
0
         6 ) == 0 ) )
654
0
  {
655
0
    chunk_data_end_offset = table_section->start_offset - table_section->size;
656
0
  }
657
  /* A table2 section where the chunk data is stored 1 section before
658
   */
659
0
  else if( last_chunk_data_offset < table_section->start_offset )
660
0
  {
661
0
    chunk_data_end_offset = table_section->start_offset;
662
0
  }
663
  /* A table section that contains the chunk data
664
   */
665
0
  else if( last_chunk_data_offset < table_section->end_offset )
666
0
  {
667
0
    chunk_data_end_offset = table_section->end_offset;
668
0
  }
669
0
  if( last_chunk_data_offset < chunk_data_end_offset )
670
0
  {
671
0
    last_chunk_data_size = chunk_data_end_offset - last_chunk_data_offset;
672
0
  }
673
0
  else
674
0
  {
675
#if defined( HAVE_DEBUG_OUTPUT )
676
    if( libcnotify_verbose != 0 )
677
    {
678
      libcnotify_printf(
679
       "%s: invalid last entry: %" PRIu32 " offset value exceeds table section end offset.\n",
680
       function,
681
       table_entry_index );
682
    }
683
#endif
684
0
    corrupted = 1;
685
0
  }
686
0
  if( last_chunk_data_size <= 0 )
687
0
  {
688
#if defined( HAVE_DEBUG_OUTPUT )
689
    if( libcnotify_verbose != 0 )
690
    {
691
      libcnotify_printf(
692
       "%s: invalid last entry: %" PRIu32 " size value is zero or less.\n",
693
       function,
694
       table_entry_index );
695
    }
696
#endif
697
0
    corrupted = 1;
698
0
  }
699
0
  if( last_chunk_data_size > (off64_t) INT32_MAX )
700
0
  {
701
#if defined( HAVE_DEBUG_OUTPUT )
702
    if( libcnotify_verbose != 0 )
703
    {
704
      libcnotify_printf(
705
       "%s: invalid last entry: %" PRIu32 " size value exceeds maximum.\n",
706
       function,
707
       table_entry_index );
708
    }
709
#endif
710
0
    corrupted = 1;
711
0
  }
712
0
  if( is_compressed != 0 )
713
0
  {
714
0
    range_flags = LIBEWF_RANGE_FLAG_IS_COMPRESSED;
715
0
  }
716
0
  else
717
0
  {
718
0
    range_flags = LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
719
0
  }
720
0
  if( corrupted != 0 )
721
0
  {
722
0
    range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
723
0
  }
724
0
  if( tainted != 0 )
725
0
  {
726
0
    range_flags |= LIBEWF_RANGE_FLAG_IS_TAINTED;
727
0
  }
728
#if defined( HAVE_DEBUG_OUTPUT )
729
  if( libcnotify_verbose != 0 )
730
  {
731
    libcnotify_printf(
732
     "%s: table entry: %05" PRIu32 " chunk\t\t\t: %" PRIu64 "\n",
733
     function,
734
     table_entry_index,
735
     chunk_index );
736
737
    libcnotify_printf(
738
     "%s: table entry: %05" PRIu32 " base offset\t\t: 0x%08" PRIx64 "\n",
739
     function,
740
     table_entry_index,
741
     base_offset );
742
743
    libcnotify_printf(
744
     "%s: table entry: %05" PRIu32 " chunk data offset\t: %" PRIu32 " (0x%08" PRIx32 ")\n",
745
     function,
746
     table_entry_index,
747
     current_offset,
748
     current_offset );
749
750
    libcnotify_printf(
751
     "%s: table entry: %05" PRIu32 " chunk data size\t\t: %" PRIu32 " (calculated)\n",
752
     function,
753
     table_entry_index,
754
     last_chunk_data_size );
755
756
    libcnotify_printf(
757
     "%s: table entry: %05" PRIu32 " chunk data flags:\n",
758
     function,
759
     table_entry_index );
760
761
    if( is_compressed != 0 )
762
    {
763
      libcnotify_printf(
764
       "\tIs compressed\n" );
765
    }
766
    else
767
    {
768
      libcnotify_printf(
769
       "\tHas checksum\n" );
770
    }
771
    if( corrupted != 0 )
772
    {
773
      libcnotify_printf(
774
       "\tIs corrupted\n" );
775
    }
776
    else if( tainted != 0 )
777
    {
778
      libcnotify_printf(
779
       "\tIs tainted\n" );
780
    }
781
    libcnotify_printf(
782
     "\n" );
783
  }
784
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
785
786
0
  if( libfdata_list_append_element_with_mapped_size(
787
0
       chunk_group->chunks_list,
788
0
       &element_index,
789
0
       file_io_pool_entry,
790
0
       last_chunk_data_offset,
791
0
       (size64_t) last_chunk_data_size,
792
0
       range_flags,
793
0
       chunk_size,
794
0
       error ) != 1 )
795
0
  {
796
0
    libcerror_error_set(
797
0
     error,
798
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
799
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
800
0
     "%s: unable to append element: %" PRIu32 " with mapped size to chunks list.",
801
0
     function,
802
0
     table_entry_index );
803
804
0
    return( -1 );
805
0
  }
806
0
  return( 1 );
807
0
}
808
809
/* Fills the chunks list from the EWF version 2 sector table entries
810
 * Returns 1 if successful or -1 on error
811
 */
812
int libewf_chunk_group_fill_v2(
813
     libewf_chunk_group_t *chunk_group,
814
     uint64_t chunk_index,
815
     size32_t chunk_size,
816
     int file_io_pool_entry,
817
     libewf_section_descriptor_t *table_section,
818
     uint32_t number_of_entries,
819
     const uint8_t *table_entries_data,
820
     size_t table_entries_data_size,
821
     uint8_t tainted,
822
     libcerror_error_t **error )
823
0
{
824
0
  static char *function      = "libewf_chunk_group_fill_v2";
825
0
  size_t data_offset         = 0;
826
0
  uint64_t chunk_data_offset = 0;
827
0
  uint32_t chunk_data_flags  = 0;
828
0
  uint32_t chunk_data_size   = 0;
829
0
  uint32_t range_flags       = 0;
830
0
  uint32_t table_entry_index = 0;
831
0
  int element_index          = 0;
832
833
0
  if( chunk_group == NULL )
834
0
  {
835
0
    libcerror_error_set(
836
0
     error,
837
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
838
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
839
0
     "%s: invalid chunk group.",
840
0
     function );
841
842
0
    return( -1 );
843
0
  }
844
0
  if( table_section == NULL )
845
0
  {
846
0
    libcerror_error_set(
847
0
     error,
848
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
849
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
850
0
     "%s: invalid table section.",
851
0
     function );
852
853
0
    return( -1 );
854
0
  }
855
0
  if( table_entries_data == NULL )
856
0
  {
857
0
    libcerror_error_set(
858
0
     error,
859
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
860
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
861
0
     "%s: invalid table entries data.",
862
0
     function );
863
864
0
    return( -1 );
865
0
  }
866
0
  if( table_entries_data_size > (size_t) SSIZE_MAX )
867
0
  {
868
0
    libcerror_error_set(
869
0
     error,
870
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
871
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
872
0
     "%s: invalid table entries data size value exceeds maximum.",
873
0
     function );
874
875
0
    return( -1 );
876
0
  }
877
0
  for( table_entry_index = 0;
878
0
       table_entry_index < number_of_entries;
879
0
       table_entry_index++ )
880
0
  {
881
0
    byte_stream_copy_to_uint64_little_endian(
882
0
     ( (ewf_table_entry_v2_t *) &( table_entries_data[ data_offset ] ) )->chunk_data_offset,
883
0
     chunk_data_offset );
884
885
0
    byte_stream_copy_to_uint32_little_endian(
886
0
     ( (ewf_table_entry_v2_t *) &( table_entries_data[ data_offset ] ) )->chunk_data_size,
887
0
     chunk_data_size );
888
889
0
    byte_stream_copy_to_uint32_little_endian(
890
0
     ( (ewf_table_entry_v2_t *) &( table_entries_data[ data_offset ] ) )->chunk_data_flags,
891
0
     chunk_data_flags );
892
893
0
    data_offset += sizeof( ewf_table_entry_v2_t );
894
895
#if defined( HAVE_DEBUG_OUTPUT )
896
    if( libcnotify_verbose != 0 )
897
    {
898
      libcnotify_printf(
899
       "%s: table entry: %05" PRIu32 " chunk\t\t\t: %" PRIu64 "\n",
900
       function,
901
       table_entry_index,
902
       chunk_index );
903
904
      if( ( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_IS_COMPRESSED ) != 0 )
905
       && ( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_USES_PATTERN_FILL ) != 0 ) )
906
      {
907
        libcnotify_printf(
908
         "%s: table entry: %05" PRIu32 " chunk pattern fill\t: 0x%08" PRIx64 "\n",
909
         function,
910
         table_entry_index,
911
         chunk_data_offset );
912
      }
913
      else
914
      {
915
        libcnotify_printf(
916
         "%s: table entry: %05" PRIu32 " chunk data offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
917
         function,
918
         table_entry_index,
919
         chunk_data_offset,
920
         chunk_data_offset );
921
      }
922
      libcnotify_printf(
923
       "%s: table entry: %05" PRIu32 " chunk data size\t\t: %" PRIu32 "\n",
924
       function,
925
       table_entry_index,
926
       chunk_data_size );
927
928
      libcnotify_printf(
929
       "%s: table entry: %05" PRIu32 " chunk data flags\t\t: 0x%08" PRIx32 "\n",
930
       function,
931
       table_entry_index,
932
       chunk_data_flags );
933
934
      if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_IS_COMPRESSED ) != 0 )
935
      {
936
        libcnotify_printf(
937
         "\tIs compressed\n" );
938
      }
939
      if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_HAS_CHECKSUM ) != 0 )
940
      {
941
        libcnotify_printf(
942
         "\tHas checksum\n" );
943
      }
944
      if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_USES_PATTERN_FILL ) != 0 )
945
      {
946
        libcnotify_printf(
947
         "\tUses pattern fill\n" );
948
      }
949
      libcnotify_printf(
950
       "\n" );
951
    }
952
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
953
954
0
    range_flags = 0;
955
956
0
    if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_IS_COMPRESSED ) != 0 )
957
0
    {
958
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_COMPRESSED;
959
960
0
      if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_USES_PATTERN_FILL ) != 0 )
961
0
      {
962
0
        range_flags |= LIBEWF_RANGE_FLAG_USES_PATTERN_FILL;
963
0
      }
964
0
    }
965
0
    if( ( chunk_data_flags & LIBEWF_CHUNK_DATA_FLAG_HAS_CHECKSUM ) != 0 )
966
0
    {
967
0
      range_flags |= LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
968
0
    }
969
/* TODO handle corruption e.g. check for zero data
970
    if( ( ( chunk_data_flags & 0x00000007UL ) != 1 )
971
     || ( ( chunk_data_flags & 0x00000007UL ) != 2 )
972
     || ( ( chunk_data_flags & 0x00000007UL ) != 5 ) )
973
    {
974
    }
975
*/
976
#if defined( HAVE_VERBOSE_OUTPUT )
977
    if( libcnotify_verbose != 0 )
978
    {
979
      if( ( chunk_data_flags & ~( 0x00000007UL ) ) != 0 )
980
      {
981
        libcnotify_printf(
982
         "%s: unsupported chunk data flags: 0x%08" PRIx32 " in table entry: %" PRIu32 "\n",
983
         function,
984
         chunk_data_flags,
985
         table_entry_index );
986
      }
987
    }
988
#endif
989
0
    if( tainted != 0 )
990
0
    {
991
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_TAINTED;
992
0
    }
993
0
    if( ( range_flags & LIBEWF_RANGE_FLAG_USES_PATTERN_FILL ) != 0 )
994
0
    {
995
0
      chunk_data_offset = table_section->start_offset + sizeof( ewf_table_header_v2_t ) + data_offset - sizeof( ewf_table_entry_v2_t );
996
0
      chunk_data_size   = 8;
997
0
    }
998
0
    if( libfdata_list_append_element_with_mapped_size(
999
0
         chunk_group->chunks_list,
1000
0
         &element_index,
1001
0
         file_io_pool_entry,
1002
0
         chunk_data_offset,
1003
0
         (size64_t) chunk_data_size,
1004
0
         range_flags,
1005
0
         chunk_size,
1006
0
         error ) != 1 )
1007
0
    {
1008
0
      libcerror_error_set(
1009
0
       error,
1010
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1011
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1012
0
       "%s: unable to append element: %" PRIu32 " with mapped size to chunks list.",
1013
0
       function,
1014
0
       table_entry_index );
1015
1016
0
      return( -1 );
1017
0
    }
1018
0
    chunk_index++;
1019
0
  }
1020
0
  return( 1 );
1021
0
}
1022
1023
/* Corrects the chunks list from the offsets
1024
 * Returns 1 if successful or -1 on error
1025
 */
1026
int libewf_chunk_group_correct_v1(
1027
     libewf_chunk_group_t *chunk_group,
1028
     uint64_t chunk_index,
1029
     size32_t chunk_size LIBEWF_ATTRIBUTE_UNUSED,
1030
     int file_io_pool_entry,
1031
     libewf_section_descriptor_t *table_section,
1032
     off64_t base_offset,
1033
     uint32_t number_of_entries,
1034
     const uint8_t *table_entries_data,
1035
     size_t table_entries_data_size,
1036
     uint8_t tainted,
1037
     libcerror_error_t **error )
1038
0
{
1039
0
  static char *function              = "libewf_chunk_group_correct_v1";
1040
0
  off64_t last_chunk_data_offset     = 0;
1041
0
  off64_t last_chunk_data_size       = 0;
1042
0
  off64_t previous_chunk_data_offset = 0;
1043
0
  size64_t previous_chunk_data_size  = 0;
1044
0
  uint32_t chunk_data_size           = 0;
1045
0
  uint32_t current_offset            = 0;
1046
0
  uint32_t next_offset               = 0;
1047
0
  uint32_t previous_range_flags      = 0;
1048
0
  uint32_t range_flags               = 0;
1049
0
  uint32_t stored_offset             = 0;
1050
0
  uint32_t table_entry_index         = 0;
1051
0
  uint8_t corrupted                  = 0;
1052
0
  uint8_t is_compressed              = 0;
1053
0
  uint8_t mismatch                   = 0;
1054
0
  uint8_t overflow                   = 0;
1055
0
  uint8_t update_data_range          = 0;
1056
0
  int previous_file_io_pool_entry    = 0;
1057
1058
0
  LIBEWF_UNREFERENCED_PARAMETER( chunk_size )
1059
1060
0
  if( chunk_group == NULL )
1061
0
  {
1062
0
    libcerror_error_set(
1063
0
     error,
1064
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1065
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1066
0
     "%s: invalid chunk group.",
1067
0
     function );
1068
1069
0
    return( -1 );
1070
0
  }
1071
0
  if( table_section == NULL )
1072
0
  {
1073
0
    libcerror_error_set(
1074
0
     error,
1075
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1076
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1077
0
     "%s: invalid table section.",
1078
0
     function );
1079
1080
0
    return( -1 );
1081
0
  }
1082
0
  if( base_offset < 0 )
1083
0
  {
1084
0
    libcerror_error_set(
1085
0
     error,
1086
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1087
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1088
0
     "%s: invalid base offset.",
1089
0
     function );
1090
1091
0
    return( -1 );
1092
0
  }
1093
0
  if( table_entries_data == NULL )
1094
0
  {
1095
0
    libcerror_error_set(
1096
0
     error,
1097
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1098
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1099
0
     "%s: invalid table entries data.",
1100
0
     function );
1101
1102
0
    return( -1 );
1103
0
  }
1104
0
  if( table_entries_data_size > (size_t) SSIZE_MAX )
1105
0
  {
1106
0
    libcerror_error_set(
1107
0
     error,
1108
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1109
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1110
0
     "%s: invalid table entries data size value exceeds maximum.",
1111
0
     function );
1112
1113
0
    return( -1 );
1114
0
  }
1115
0
  byte_stream_copy_to_uint32_little_endian(
1116
0
   ( ( (ewf_table_entry_v1_t *) table_entries_data )[ table_entry_index ] ).chunk_data_offset,
1117
0
   stored_offset );
1118
1119
0
  while( table_entry_index < ( number_of_entries - 1 ) )
1120
0
  {
1121
0
    if( overflow == 0 )
1122
0
    {
1123
0
      is_compressed  = (uint8_t) ( stored_offset >> 31 );
1124
0
      current_offset = stored_offset & 0x7fffffffUL;
1125
0
    }
1126
0
    else
1127
0
    {
1128
0
      current_offset = stored_offset;
1129
0
    }
1130
0
    byte_stream_copy_to_uint32_little_endian(
1131
0
     ( ( (ewf_table_entry_v1_t *) table_entries_data )[ table_entry_index + 1 ] ).chunk_data_offset,
1132
0
     stored_offset );
1133
1134
0
    if( overflow == 0 )
1135
0
    {
1136
0
      next_offset = stored_offset & 0x7fffffffUL;
1137
0
    }
1138
0
    else
1139
0
    {
1140
0
      next_offset = stored_offset;
1141
0
    }
1142
0
    corrupted = 0;
1143
1144
    /* This is to compensate for the crappy > 2 GiB segment file solution in EnCase 6.7
1145
     */
1146
0
    if( next_offset < current_offset )
1147
0
    {
1148
0
      if( stored_offset < current_offset )
1149
0
      {
1150
#if defined( HAVE_DEBUG_OUTPUT )
1151
        if( libcnotify_verbose != 0 )
1152
        {
1153
          libcnotify_printf(
1154
           "%s: chunk: %" PRIu64 " offset: %" PRIu32 " larger than stored offset: %" PRIu32 ".\n",
1155
           function,
1156
           chunk_index,
1157
           current_offset,
1158
           stored_offset );
1159
        }
1160
#endif
1161
0
        corrupted = 1;
1162
0
      }
1163
#if defined( HAVE_DEBUG_OUTPUT )
1164
      else if( libcnotify_verbose != 0 )
1165
      {
1166
        libcnotify_printf(
1167
         "%s: chunk: %" PRIu64 " offset: %" PRIu32 " larger than next offset: %" PRIu32 ".\n",
1168
         function,
1169
         chunk_index,
1170
         current_offset,
1171
         next_offset );
1172
      }
1173
#endif
1174
0
      chunk_data_size = stored_offset - current_offset;
1175
0
    }
1176
0
    else
1177
0
    {
1178
0
      chunk_data_size = next_offset - current_offset;
1179
0
    }
1180
0
    if( chunk_data_size == 0 )
1181
0
    {
1182
0
      if( libcnotify_verbose != 0 )
1183
0
      {
1184
0
        libcnotify_printf(
1185
0
         "%s: invalid chunk: %" PRIu64 " size value is zero.\n",
1186
0
         function,
1187
0
         chunk_index );
1188
0
      }
1189
0
      corrupted = 1;
1190
0
    }
1191
0
    if( chunk_data_size > (uint32_t) INT32_MAX )
1192
0
    {
1193
0
      if( libcnotify_verbose != 0 )
1194
0
      {
1195
0
        libcnotify_printf(
1196
0
         "%s: invalid chunk: %" PRIu64 " size value exceeds maximum.\n",
1197
0
         function,
1198
0
         chunk_index );
1199
0
      }
1200
0
      corrupted = 1;
1201
0
    }
1202
0
    range_flags = LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
1203
1204
0
    if( is_compressed != 0 )
1205
0
    {
1206
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_COMPRESSED;
1207
0
    }
1208
0
    if( corrupted != 0 )
1209
0
    {
1210
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
1211
0
    }
1212
0
    if( tainted != 0 )
1213
0
    {
1214
0
      range_flags |= LIBEWF_RANGE_FLAG_IS_TAINTED;
1215
0
    }
1216
#if defined( HAVE_DEBUG_OUTPUT )
1217
    if( libcnotify_verbose != 0 )
1218
    {
1219
      libcnotify_printf(
1220
       "%s: table entry: %05" PRIu32 " chunk\t\t\t: %" PRIu64 "\n",
1221
       function,
1222
       table_entry_index,
1223
       chunk_index );
1224
1225
      libcnotify_printf(
1226
       "%s: table entry: %05" PRIu32 " base offset\t\t: 0x%08" PRIx64 "\n",
1227
       function,
1228
       table_entry_index,
1229
       base_offset );
1230
1231
      libcnotify_printf(
1232
       "%s: table entry: %05" PRIu32 " chunk data offset\t: %" PRIu32 " (0x%08" PRIx32 ")\n",
1233
       function,
1234
       table_entry_index,
1235
       current_offset,
1236
       current_offset );
1237
1238
      libcnotify_printf(
1239
       "%s: table entry: %05" PRIu32 " chunk data size\t: %" PRIu32 "\n",
1240
       function,
1241
       table_entry_index,
1242
       chunk_data_size );
1243
1244
      libcnotify_printf(
1245
       "%s: table entry: %05" PRIu32 " chunk data flags:\n",
1246
       function,
1247
       table_entry_index );
1248
1249
      if( is_compressed != 0 )
1250
      {
1251
        libcnotify_printf(
1252
         "\tIs compressed\n" );
1253
      }
1254
      else
1255
      {
1256
        libcnotify_printf(
1257
         "\tHas checksum\n" );
1258
      }
1259
      if( corrupted != 0 )
1260
      {
1261
        libcnotify_printf(
1262
         "\tIs corrupted\n" );
1263
      }
1264
      else if( tainted != 0 )
1265
      {
1266
        libcnotify_printf(
1267
         "\tIs tainted\n" );
1268
      }
1269
      libcnotify_printf(
1270
       "\n" );
1271
    }
1272
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1273
1274
0
    if( libfdata_list_get_element_by_index(
1275
0
         chunk_group->chunks_list,
1276
0
         table_entry_index,
1277
0
         &previous_file_io_pool_entry,
1278
0
         &previous_chunk_data_offset,
1279
0
         &previous_chunk_data_size,
1280
0
         &previous_range_flags,
1281
0
         error ) != 1 )
1282
0
    {
1283
0
      libcerror_error_set(
1284
0
       error,
1285
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1286
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1287
0
       "%s: unable to retrieve element: %" PRIu32 " from chunks list.",
1288
0
       function,
1289
0
       table_entry_index );
1290
1291
0
      return( -1 );
1292
0
    }
1293
0
    if( (off64_t) ( base_offset + current_offset ) != previous_chunk_data_offset )
1294
0
    {
1295
#if defined( HAVE_DEBUG_OUTPUT )
1296
      if( libcnotify_verbose != 0 )
1297
      {
1298
        libcnotify_printf(
1299
         "%s: chunk: %" PRIu64 " offset mismatch.\n",
1300
         function,
1301
         chunk_index );
1302
      }
1303
#endif
1304
0
      mismatch = 1;
1305
0
    }
1306
0
    else if( (size64_t) chunk_data_size != previous_chunk_data_size )
1307
0
    {
1308
#if defined( HAVE_DEBUG_OUTPUT )
1309
      if( libcnotify_verbose != 0 )
1310
      {
1311
        libcnotify_printf(
1312
         "%s: chunk: %" PRIu64 " size mismatch.\n",
1313
         function,
1314
         chunk_index );
1315
      }
1316
#endif
1317
0
      mismatch = 1;
1318
0
    }
1319
0
    else if( ( range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED )
1320
0
          != ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) )
1321
0
    {
1322
#if defined( HAVE_DEBUG_OUTPUT )
1323
      if( libcnotify_verbose != 0 )
1324
      {
1325
        libcnotify_printf(
1326
         "%s: chunk: %" PRIu64 " compression flag mismatch.\n",
1327
         function,
1328
         chunk_index );
1329
      }
1330
#endif
1331
0
      mismatch = 1;
1332
0
    }
1333
0
    else
1334
0
    {
1335
0
      mismatch = 0;
1336
0
    }
1337
0
    update_data_range = 0;
1338
1339
0
    if( mismatch != 0 )
1340
0
    {
1341
0
      if( ( corrupted == 0 )
1342
0
       && ( tainted == 0 ) )
1343
0
      {
1344
0
        update_data_range = 1;
1345
0
      }
1346
0
      else if( ( ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_CORRUPTED ) != 0 )
1347
0
            && ( corrupted == 0 ) )
1348
0
      {
1349
0
        update_data_range = 1;
1350
0
      }
1351
0
    }
1352
0
    else if( ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_TAINTED ) != 0 )
1353
0
    {
1354
0
      update_data_range = 1;
1355
0
    }
1356
0
    if( update_data_range != 0 )
1357
0
    {
1358
0
      if( libfdata_list_set_element_by_index(
1359
0
           chunk_group->chunks_list,
1360
0
           table_entry_index,
1361
0
           file_io_pool_entry,
1362
0
           base_offset + current_offset,
1363
0
           (size64_t) chunk_data_size,
1364
0
           range_flags,
1365
0
           error ) != 1 )
1366
0
      {
1367
0
        libcerror_error_set(
1368
0
         error,
1369
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1370
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1371
0
         "%s: unable to set element: %" PRIu32 " in chunks list.",
1372
0
         function,
1373
0
         table_entry_index );
1374
1375
0
        return( -1 );
1376
0
      }
1377
0
    }
1378
    /* This is to compensate for the crappy > 2 GiB segment file solution in EnCase 6.7
1379
     */
1380
0
    if( ( overflow == 0 )
1381
0
     && ( ( current_offset + chunk_data_size ) > (uint32_t) INT32_MAX ) )
1382
0
    {
1383
#if defined( HAVE_DEBUG_OUTPUT )
1384
      if( libcnotify_verbose != 0 )
1385
      {
1386
        libcnotify_printf(
1387
         "%s: chunk: %" PRIu64 " offset overflow at: %" PRIu32 ".\n",
1388
         function,
1389
         chunk_index,
1390
         current_offset );
1391
      }
1392
#endif
1393
0
      overflow      = 1;
1394
0
      is_compressed = 0;
1395
0
    }
1396
0
    table_entry_index++;
1397
0
  }
1398
0
  byte_stream_copy_to_uint32_little_endian(
1399
0
   ( ( (ewf_table_entry_v1_t *) table_entries_data )[ table_entry_index ] ).chunk_data_offset,
1400
0
   stored_offset );
1401
1402
0
  if( overflow == 0 )
1403
0
  {
1404
0
    is_compressed  = (uint8_t) ( stored_offset >> 31 );
1405
0
    current_offset = stored_offset & 0x7fffffffUL;
1406
0
  }
1407
0
  else
1408
0
  {
1409
0
    current_offset = stored_offset;
1410
0
  }
1411
0
  corrupted = 0;
1412
1413
  /* There is no indication how large the last chunk is.
1414
   * The only thing known is where it starts.
1415
   * However it can be determined using the offset of the next section.
1416
   * The size of the last chunk is determined by subtracting the last offset from the offset of the next section.
1417
   *
1418
   * The offset of the next section is either table_section->end_offset for original EWF and EWF-S01
1419
   * or table_section->start_offset for other types of EWF
1420
   */
1421
0
  last_chunk_data_offset = (off64_t) base_offset + current_offset;
1422
1423
0
  if( last_chunk_data_offset > (off64_t) INT64_MAX )
1424
0
  {
1425
0
    libcerror_error_set(
1426
0
     error,
1427
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1428
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1429
0
     "%s: invalid last chunk: %" PRIu64 " offset value exceeds maximum.",
1430
0
     function,
1431
0
     chunk_index );
1432
1433
0
    return( -1 );
1434
0
  }
1435
/* TODO fix for table2 */
1436
0
  if( last_chunk_data_offset < table_section->start_offset )
1437
0
  {
1438
0
    last_chunk_data_size = table_section->start_offset - last_chunk_data_offset;
1439
0
  }
1440
0
  else if( last_chunk_data_offset < table_section->end_offset )
1441
0
  {
1442
0
    last_chunk_data_size = table_section->end_offset - last_chunk_data_offset;
1443
0
  }
1444
#if defined( HAVE_DEBUG_OUTPUT )
1445
  else if( libcnotify_verbose != 0 )
1446
  {
1447
    libcnotify_printf(
1448
     "%s: invalid last chunk: %" PRIu64 " offset value exceeds table section end offset.\n",
1449
     function,
1450
     chunk_index );
1451
  }
1452
#endif
1453
0
  last_chunk_data_size -= table_section->size;
1454
1455
0
  if( last_chunk_data_size <= 0 )
1456
0
  {
1457
#if defined( HAVE_DEBUG_OUTPUT )
1458
    if( libcnotify_verbose != 0 )
1459
    {
1460
      libcnotify_printf(
1461
       "%s: invalid last chunk: %" PRIu64 " size value is zero or less.\n",
1462
       function,
1463
       chunk_index );
1464
    }
1465
#endif
1466
0
    corrupted = 1;
1467
0
  }
1468
0
  if( last_chunk_data_size > (off64_t) INT32_MAX )
1469
0
  {
1470
#if defined( HAVE_DEBUG_OUTPUT )
1471
    if( libcnotify_verbose != 0 )
1472
    {
1473
      libcnotify_printf(
1474
       "%s: invalid last chunk: %" PRIu64 " size value exceeds maximum.\n",
1475
       function,
1476
       chunk_index );
1477
    }
1478
#endif
1479
0
    corrupted = 1;
1480
0
  }
1481
0
  range_flags = LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
1482
1483
0
  if( is_compressed != 0 )
1484
0
  {
1485
0
    range_flags |= LIBEWF_RANGE_FLAG_IS_COMPRESSED;
1486
0
  }
1487
0
  if( corrupted != 0 )
1488
0
  {
1489
0
    range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
1490
0
  }
1491
0
  if( tainted != 0 )
1492
0
  {
1493
0
    range_flags |= LIBEWF_RANGE_FLAG_IS_TAINTED;
1494
0
  }
1495
#if defined( HAVE_DEBUG_OUTPUT )
1496
  if( libcnotify_verbose != 0 )
1497
  {
1498
    libcnotify_printf(
1499
     "%s: table entry: %05" PRIu32 " chunk\t\t\t: %" PRIu64 "\n",
1500
     function,
1501
     table_entry_index,
1502
     chunk_index );
1503
1504
    libcnotify_printf(
1505
     "%s: table entry: %05" PRIu32 " base offset\t\t: 0x%08" PRIx64 "\n",
1506
     function,
1507
     table_entry_index,
1508
     base_offset );
1509
1510
    libcnotify_printf(
1511
     "%s: table entry: %05" PRIu32 " chunk data offset\t: %" PRIu32 " (0x%08" PRIx32 ")\n",
1512
     function,
1513
     table_entry_index,
1514
     current_offset,
1515
     current_offset );
1516
1517
    libcnotify_printf(
1518
     "%s: table entry: %05" PRIu32 " chunk data size\t: %" PRIu32 " (calculated)\n",
1519
     function,
1520
     table_entry_index,
1521
     last_chunk_data_size );
1522
1523
    libcnotify_printf(
1524
     "%s: table entry: %05" PRIu32 " chunk data flags:\n",
1525
     function,
1526
     table_entry_index );
1527
1528
    if( is_compressed != 0 )
1529
    {
1530
      libcnotify_printf(
1531
       "\tIs compressed\n" );
1532
    }
1533
    else
1534
    {
1535
      libcnotify_printf(
1536
       "\tHas checksum\n" );
1537
    }
1538
    if( corrupted != 0 )
1539
    {
1540
      libcnotify_printf(
1541
       "\tIs corrupted\n" );
1542
    }
1543
    else if( tainted != 0 )
1544
    {
1545
      libcnotify_printf(
1546
       "\tIs tainted\n" );
1547
    }
1548
    libcnotify_printf(
1549
     "\n" );
1550
  }
1551
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1552
1553
0
  if( libfdata_list_get_element_by_index(
1554
0
       chunk_group->chunks_list,
1555
0
       table_entry_index,
1556
0
       &previous_file_io_pool_entry,
1557
0
       &previous_chunk_data_offset,
1558
0
       &previous_chunk_data_size,
1559
0
       &previous_range_flags,
1560
0
       error ) != 1 )
1561
0
  {
1562
0
    libcerror_error_set(
1563
0
     error,
1564
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1565
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1566
0
     "%s: unable to retrieve element: %" PRIu32 " from chunks list.",
1567
0
     function,
1568
0
     table_entry_index );
1569
1570
0
    return( -1 );
1571
0
  }
1572
0
  if( (off64_t) ( base_offset + current_offset ) != previous_chunk_data_offset )
1573
0
  {
1574
#if defined( HAVE_DEBUG_OUTPUT )
1575
    if( libcnotify_verbose != 0 )
1576
    {
1577
      libcnotify_printf(
1578
       "%s: chunk: %" PRIu64 " offset mismatch.\n",
1579
       function,
1580
       chunk_index );
1581
    }
1582
#endif
1583
0
    mismatch = 1;
1584
0
  }
1585
0
  else if( (size64_t) chunk_data_size != previous_chunk_data_size )
1586
0
  {
1587
#if defined( HAVE_DEBUG_OUTPUT )
1588
    if( libcnotify_verbose != 0 )
1589
    {
1590
      libcnotify_printf(
1591
       "%s: chunk: %" PRIu64 " size mismatch.\n",
1592
       function,
1593
       chunk_index );
1594
    }
1595
#endif
1596
0
    mismatch = 1;
1597
0
  }
1598
0
  else if( ( range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED )
1599
0
        != ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) )
1600
0
  {
1601
#if defined( HAVE_DEBUG_OUTPUT )
1602
    if( libcnotify_verbose != 0 )
1603
    {
1604
      libcnotify_printf(
1605
       "%s: chunk: %" PRIu64 " compression flag mismatch.\n",
1606
       function,
1607
       chunk_index );
1608
    }
1609
#endif
1610
0
    mismatch = 1;
1611
0
  }
1612
0
  else
1613
0
  {
1614
0
    mismatch = 0;
1615
0
  }
1616
0
  update_data_range = 0;
1617
1618
0
  if( mismatch != 0 )
1619
0
  {
1620
0
    if( ( corrupted == 0 )
1621
0
     && ( tainted == 0 ) )
1622
0
    {
1623
0
      update_data_range = 1;
1624
0
    }
1625
0
    else if( ( ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_CORRUPTED ) != 0 )
1626
0
          && ( corrupted == 0 ) )
1627
0
    {
1628
0
      update_data_range = 1;
1629
0
    }
1630
0
  }
1631
0
  else if( ( previous_range_flags & LIBEWF_RANGE_FLAG_IS_TAINTED ) != 0 )
1632
0
  {
1633
0
    update_data_range = 1;
1634
0
  }
1635
0
  if( update_data_range != 0 )
1636
0
  {
1637
0
    if( libfdata_list_set_element_by_index(
1638
0
         chunk_group->chunks_list,
1639
0
         table_entry_index,
1640
0
         file_io_pool_entry,
1641
0
         base_offset + current_offset,
1642
0
         (size64_t) chunk_data_size,
1643
0
         range_flags,
1644
0
         error ) != 1 )
1645
0
    {
1646
0
      libcerror_error_set(
1647
0
       error,
1648
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1649
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1650
0
       "%s: unable to set element: %" PRIu32 " in chunks list.",
1651
0
       function,
1652
0
       table_entry_index );
1653
1654
0
      return( -1 );
1655
0
    }
1656
0
  }
1657
#if defined( HAVE_DEBUG_OUTPUT )
1658
  if( libcnotify_verbose != 0 )
1659
  {
1660
    libcnotify_printf(
1661
     "\n" );
1662
  }
1663
#endif
1664
0
  return( 1 );
1665
0
}
1666