Coverage Report

Created: 2023-06-07 06:53

/src/libfsntfs/libfsntfs/libfsntfs_index_entry_vector.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The index entry vector functions
3
 *
4
 * Copyright (C) 2010-2023, 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 <types.h>
24
25
#include "libfsntfs_data_run.h"
26
#include "libfsntfs_definitions.h"
27
#include "libfsntfs_index_entry.h"
28
#include "libfsntfs_index_entry_vector.h"
29
#include "libfsntfs_io_handle.h"
30
#include "libfsntfs_libcdata.h"
31
#include "libfsntfs_libcerror.h"
32
#include "libfsntfs_libfdata.h"
33
#include "libfsntfs_mft_attribute.h"
34
#include "libfsntfs_unused.h"
35
36
/* Creates an index entry vector
37
 * Make sure the value index_entry_vector is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsntfs_index_entry_vector_initialize(
41
     libfdata_vector_t **index_entry_vector,
42
     libfsntfs_io_handle_t *io_handle,
43
     libfsntfs_mft_attribute_t *mft_attribute,
44
     uint32_t index_entry_size,
45
     libcerror_error_t **error )
46
532
{
47
532
  libfdata_vector_t *safe_index_entry_vector   = NULL;
48
532
  libfsntfs_data_run_t *data_run               = NULL;
49
532
  static char *function                        = "libfsntfs_index_entry_vector_initialize";
50
532
  size64_t attribute_data_vcn_size             = 0;
51
532
  size64_t calculated_allocated_data_size      = 0;
52
532
  size64_t stored_allocated_data_size          = 0;
53
532
  off64_t attribute_data_vcn_offset            = 0;
54
532
  off64_t calculated_attribute_data_vcn_offset = 0;
55
532
  uint16_t attribute_data_flags                = 0;
56
532
  int attribute_index                          = 0;
57
532
  int entry_index                              = 0;
58
532
  int number_of_entries                        = 0;
59
532
  int segment_index                            = 0;
60
61
532
  if( index_entry_vector == NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
67
0
     "%s: invalid index entry vector.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
532
  if( *index_entry_vector != NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
77
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
78
0
     "%s: invalid index entry vector value already set.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
532
  if( io_handle == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
88
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
89
0
     "%s: invalid IO handle.",
90
0
     function );
91
92
0
    return( -1 );
93
0
  }
94
532
  if( io_handle->cluster_block_size == 0 )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
99
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
100
0
     "%s: invalid IO handle - cluster block size value out of bounds.",
101
0
     function );
102
103
0
    return( -1 );
104
0
  }
105
532
  if( index_entry_size == 0 )
106
2
  {
107
2
    libcerror_error_set(
108
2
     error,
109
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
110
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
111
2
     "%s: invalid index entry size value out of bounds.",
112
2
     function );
113
114
2
    return( -1 );
115
2
  }
116
530
  if( libfsntfs_mft_attribute_get_data_flags(
117
530
       mft_attribute,
118
530
       &attribute_data_flags,
119
530
       error ) != 1 )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
124
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
125
0
     "%s: unable to retrieve attribute data flags.",
126
0
     function );
127
128
0
    goto on_error;
129
0
  }
130
530
  if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 )
131
2
  {
132
2
    libcerror_error_set(
133
2
     error,
134
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
135
2
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
136
2
     "%s: unsupported compressed attribute data.",
137
2
     function );
138
139
2
    goto on_error;
140
2
  }
141
528
  if( libfsntfs_mft_attribute_get_allocated_data_size(
142
528
       mft_attribute,
143
528
       &stored_allocated_data_size,
144
528
       error ) != 1 )
145
0
  {
146
0
    libcerror_error_set(
147
0
     error,
148
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
149
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
150
0
     "%s: unable to retrieve attribute allocated data size.",
151
0
     function );
152
153
0
    goto on_error;
154
0
  }
155
528
  if( libfdata_vector_initialize(
156
528
       &safe_index_entry_vector,
157
528
       (size64_t) index_entry_size,
158
528
       NULL,
159
528
       NULL,
160
528
       NULL,
161
528
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_index_entry_vector_read_element_data,
162
528
       NULL,
163
528
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
164
528
       error ) != 1 )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
169
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
170
0
     "%s: unable to create index entry vector.",
171
0
     function );
172
173
0
    goto on_error;
174
0
  }
175
890
  while( mft_attribute != NULL )
176
627
  {
177
627
    if( libfsntfs_mft_attribute_get_data_vcn_range(
178
627
         mft_attribute,
179
627
         (uint64_t *) &attribute_data_vcn_offset,
180
627
         (uint64_t *) &attribute_data_vcn_size,
181
627
         error ) != 1 )
182
40
    {
183
40
      libcerror_error_set(
184
40
       error,
185
40
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
40
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
187
40
       "%s: unable to retrieve attribute data VCN range.",
188
40
       function );
189
190
40
      goto on_error;
191
40
    }
192
587
    if( attribute_data_vcn_size != 0xffffffffffffffffULL )
193
569
    {
194
569
      if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) )
195
34
      {
196
34
        libcerror_error_set(
197
34
         error,
198
34
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
199
34
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
200
34
         "%s: invalid attribute data first VCN value out of bounds.",
201
34
         function );
202
203
34
        goto on_error;
204
34
      }
205
535
      if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) )
206
47
      {
207
47
        libcerror_error_set(
208
47
         error,
209
47
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
47
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
211
47
         "%s: invalid attribute data last VCN value out of bounds.",
212
47
         function );
213
214
47
        goto on_error;
215
47
      }
216
488
      if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size )
217
57
      {
218
57
        libcerror_error_set(
219
57
         error,
220
57
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
221
57
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
222
57
         "%s: invalid attribute data first VCN value out of bounds.",
223
57
         function );
224
225
57
        goto on_error;
226
57
      }
227
431
      attribute_data_vcn_size   += 1;
228
431
      attribute_data_vcn_size   -= attribute_data_vcn_offset;
229
431
      attribute_data_vcn_offset *= io_handle->cluster_block_size;
230
431
      attribute_data_vcn_size   *= io_handle->cluster_block_size;
231
232
431
      if( ( calculated_attribute_data_vcn_offset != 0 )
233
431
       && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) )
234
83
      {
235
83
        libcerror_error_set(
236
83
         error,
237
83
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
238
83
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
239
83
         "%s: invalid attribute data VCN offset value out of bounds.",
240
83
         function );
241
242
83
        goto on_error;
243
83
      }
244
348
      calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size;
245
348
    }
246
366
    if( libfsntfs_mft_attribute_get_number_of_data_runs(
247
366
         mft_attribute,
248
366
         &number_of_entries,
249
366
         error ) != 1 )
250
0
    {
251
0
      libcerror_error_set(
252
0
       error,
253
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
254
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
255
0
       "%s: unable to retrieve attribute: %d number of data runs.",
256
0
       function,
257
0
       attribute_index );
258
259
0
      goto on_error;
260
0
    }
261
366
    for( entry_index = 0;
262
1.64k
         entry_index < number_of_entries;
263
1.28k
         entry_index++ )
264
1.28k
    {
265
1.28k
      if( libfsntfs_mft_attribute_get_data_run_by_index(
266
1.28k
           mft_attribute,
267
1.28k
           entry_index,
268
1.28k
           &data_run,
269
1.28k
           error ) != 1 )
270
0
      {
271
0
        libcerror_error_set(
272
0
         error,
273
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
275
0
         "%s: unable to retrieve attribute: %d data run: %d.",
276
0
         function,
277
0
         attribute_index,
278
0
         entry_index );
279
280
0
        goto on_error;
281
0
      }
282
1.28k
      if( data_run == NULL )
283
0
      {
284
0
        libcerror_error_set(
285
0
         error,
286
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
287
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
288
0
         "%s: missing attribute: %d data run: %d.",
289
0
         function,
290
0
         attribute_index,
291
0
         entry_index );
292
293
0
        goto on_error;
294
0
      }
295
1.28k
      if( libfdata_vector_append_segment(
296
1.28k
           safe_index_entry_vector,
297
1.28k
           &segment_index,
298
1.28k
           0,
299
1.28k
           data_run->start_offset,
300
1.28k
           data_run->size,
301
1.28k
           0,
302
1.28k
           error ) != 1 )
303
4
      {
304
4
        libcerror_error_set(
305
4
         error,
306
4
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
307
4
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
308
4
         "%s: unable to append attribute: %d data run: %d vector segment.",
309
4
         function,
310
4
         attribute_index,
311
4
         entry_index );
312
313
4
        goto on_error;
314
4
      }
315
1.28k
      calculated_allocated_data_size += data_run->size;
316
1.28k
    }
317
362
    attribute_index++;
318
319
362
    if( libfsntfs_mft_attribute_get_next_attribute(
320
362
         mft_attribute,
321
362
         &mft_attribute,
322
362
         error ) != 1 )
323
0
    {
324
0
      libcerror_error_set(
325
0
       error,
326
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
327
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
328
0
       "%s: unable to retrieve next MFT attribute: %d.",
329
0
       function,
330
0
       attribute_index );
331
332
0
      goto on_error;
333
0
    }
334
362
  }
335
263
  if( calculated_allocated_data_size != stored_allocated_data_size )
336
98
  {
337
98
    libcerror_error_set(
338
98
     error,
339
98
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
340
98
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
341
98
     "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".",
342
98
     function,
343
98
     calculated_allocated_data_size,
344
98
     stored_allocated_data_size );
345
346
98
    goto on_error;
347
98
  }
348
165
  *index_entry_vector = safe_index_entry_vector;
349
350
165
  return( 1 );
351
352
365
on_error:
353
365
  if( safe_index_entry_vector != NULL )
354
363
  {
355
363
    libfdata_vector_free(
356
363
     &safe_index_entry_vector,
357
363
     NULL );
358
363
  }
359
365
  return( -1 );
360
263
}
361
362
/* Reads the index entry
363
 * Callback function for the index entry vector
364
 * Returns 1 if successful or -1 on error
365
 */
366
int libfsntfs_index_entry_vector_read_element_data(
367
     intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED,
368
     libbfio_handle_t *file_io_handle,
369
     libfdata_vector_t *vector,
370
     libfdata_cache_t *cache,
371
     int element_index,
372
     int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED,
373
     off64_t index_entry_offset,
374
     size64_t index_entry_size,
375
     uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
376
     uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
377
     libcerror_error_t **error )
378
712
{
379
712
  libfsntfs_index_entry_t *index_entry = NULL;
380
712
  static char *function                = "libfsntfs_index_entry_vector_read_element_data";
381
382
712
  LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle )
383
712
  LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index )
384
712
  LIBFSNTFS_UNREFERENCED_PARAMETER( element_flags )
385
712
  LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags )
386
387
712
  if( (uint64_t) element_index > (uint64_t) UINT32_MAX )
388
0
  {
389
0
    libcerror_error_set(
390
0
     error,
391
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
392
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
393
0
     "%s: invalid element index value out of bounds.",
394
0
     function );
395
396
0
    return( -1 );
397
0
  }
398
712
  if( (uint64_t) index_entry_size > (uint64_t) UINT32_MAX )
399
0
  {
400
0
    libcerror_error_set(
401
0
     error,
402
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
403
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
404
0
     "%s: invalid index entry size value out of bounds.",
405
0
     function );
406
407
0
    return( -1 );
408
0
  }
409
712
  if( libfsntfs_index_entry_initialize(
410
712
       &index_entry,
411
712
       error ) != 1 )
412
0
  {
413
0
    libcerror_error_set(
414
0
     error,
415
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
416
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
417
0
     "%s: unable to create index entry.",
418
0
     function );
419
420
0
    goto on_error;
421
0
  }
422
712
  if( libfsntfs_index_entry_read_file_io_handle(
423
712
       index_entry,
424
712
       file_io_handle,
425
712
       index_entry_offset,
426
712
       (uint32_t) index_entry_size,
427
712
       (uint32_t) element_index,
428
712
       error ) != 1 )
429
74
  {
430
74
    libcerror_error_set(
431
74
     error,
432
74
     LIBCERROR_ERROR_DOMAIN_IO,
433
74
     LIBCERROR_IO_ERROR_READ_FAILED,
434
74
     "%s: unable to read index entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
435
74
     function,
436
74
     element_index,
437
74
     index_entry_offset,
438
74
     index_entry_offset );
439
440
74
    goto on_error;
441
74
  }
442
638
  if( libfdata_vector_set_element_value_by_index(
443
638
       vector,
444
638
       (intptr_t *) file_io_handle,
445
638
       cache,
446
638
       element_index,
447
638
       (intptr_t *) index_entry->node,
448
638
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_index_node_free,
449
638
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
450
638
       error ) != 1 )
451
0
  {
452
0
    libcerror_error_set(
453
0
     error,
454
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
455
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
456
0
     "%s: unable to set index node as element value.",
457
0
     function );
458
459
0
    goto on_error;
460
0
  }
461
638
  index_entry->node = NULL;
462
463
638
  if( libfsntfs_index_entry_free(
464
638
       &index_entry,
465
638
       error ) != 1 )
466
0
  {
467
0
    libcerror_error_set(
468
0
     error,
469
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
470
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
471
0
     "%s: unable to free index entry.",
472
0
     function );
473
474
0
    goto on_error;
475
0
  }
476
638
  return( 1 );
477
478
74
on_error:
479
74
  if( index_entry != NULL )
480
74
  {
481
74
    libfsntfs_index_entry_free(
482
74
     &index_entry,
483
74
     NULL );
484
74
  }
485
74
  return( -1 );
486
638
}
487