Coverage Report

Created: 2023-06-07 06:53

/src/libfsntfs/libfsntfs/libfsntfs_index_node.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Index node 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 <memory.h>
24
#include <types.h>
25
26
#include "libfsntfs_definitions.h"
27
#include "libfsntfs_index_node.h"
28
#include "libfsntfs_index_node_header.h"
29
#include "libfsntfs_index_value.h"
30
#include "libfsntfs_libcdata.h"
31
#include "libfsntfs_libcerror.h"
32
#include "libfsntfs_libcnotify.h"
33
34
#include "fsntfs_index.h"
35
36
/* Creates an index node
37
 * Make sure the value index_node is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsntfs_index_node_initialize(
41
     libfsntfs_index_node_t **index_node,
42
     libcerror_error_t **error )
43
2.06k
{
44
2.06k
  static char *function = "libfsntfs_index_node_initialize";
45
46
2.06k
  if( index_node == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid index node.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
2.06k
  if( *index_node != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid index node value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
2.06k
  *index_node = memory_allocate_structure(
69
2.06k
                 libfsntfs_index_node_t );
70
71
2.06k
  if( *index_node == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create index node.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
2.06k
  if( memory_set(
83
2.06k
       *index_node,
84
2.06k
       0,
85
2.06k
       sizeof( libfsntfs_index_node_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear index node.",
92
0
     function );
93
94
0
    memory_free(
95
0
     *index_node );
96
97
0
    *index_node = NULL;
98
99
0
    return( -1 );
100
0
  }
101
2.06k
  if( libcdata_array_initialize(
102
2.06k
       &( ( *index_node )->values_array ),
103
2.06k
       0,
104
2.06k
       error ) != 1 )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
109
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
110
0
     "%s: unable to create values array.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
2.06k
  return( 1 );
116
117
0
on_error:
118
0
  if( *index_node != NULL )
119
0
  {
120
0
    memory_free(
121
0
     *index_node );
122
123
0
    *index_node = NULL;
124
0
  }
125
0
  return( -1 );
126
2.06k
}
127
128
/* Frees an index node
129
 * Returns 1 if successful or -1 on error
130
 */
131
int libfsntfs_index_node_free(
132
     libfsntfs_index_node_t **index_node,
133
     libcerror_error_t **error )
134
2.06k
{
135
2.06k
  static char *function = "libfsntfs_index_node_free";
136
2.06k
  int result            = 1;
137
138
2.06k
  if( index_node == NULL )
139
0
  {
140
0
    libcerror_error_set(
141
0
     error,
142
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
144
0
     "%s: invalid index node.",
145
0
     function );
146
147
0
    return( -1 );
148
0
  }
149
2.06k
  if( *index_node != NULL )
150
2.06k
  {
151
2.06k
    if( ( *index_node )->header != NULL )
152
1.95k
    {
153
1.95k
      if( libfsntfs_index_node_header_free(
154
1.95k
           &( ( *index_node )->header ),
155
1.95k
           error ) != 1 )
156
0
      {
157
0
        libcerror_error_set(
158
0
         error,
159
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
160
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
161
0
         "%s: unable to free index node header.",
162
0
         function );
163
164
0
        result = -1;
165
0
      }
166
1.95k
    }
167
2.06k
    if( libcdata_array_free(
168
2.06k
         &( ( *index_node )->values_array ),
169
2.06k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_index_value_free,
170
2.06k
         error ) != 1 )
171
0
    {
172
0
      libcerror_error_set(
173
0
       error,
174
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
175
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
176
0
       "%s: unable to free values array.",
177
0
       function );
178
179
0
      result = -1;
180
0
    }
181
2.06k
    memory_free(
182
2.06k
     *index_node );
183
184
2.06k
    *index_node = NULL;
185
2.06k
  }
186
2.06k
  return( result );
187
2.06k
}
188
189
/* Reads the index node header
190
 * Returns 1 if successful or -1 on error
191
 */
192
int libfsntfs_index_node_read_header(
193
     libfsntfs_index_node_t *index_node,
194
     const uint8_t *data,
195
     size_t data_size,
196
     size_t data_offset,
197
     libcerror_error_t **error )
198
2.06k
{
199
2.06k
  static char *function = "libfsntfs_index_node_read_header";
200
201
2.06k
  if( index_node == NULL )
202
0
  {
203
0
    libcerror_error_set(
204
0
     error,
205
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
206
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
207
0
     "%s: invalid index node.",
208
0
     function );
209
210
0
    return( -1 );
211
0
  }
212
2.06k
  if( index_node->header != NULL )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
218
0
     "%s: invalid index node - header value already set.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
2.06k
  if( data_size > (size_t) SSIZE_MAX )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
228
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
229
0
     "%s: data size value exceeds maximum.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
2.06k
  if( data_offset >= data_size )
235
2
  {
236
2
    libcerror_error_set(
237
2
     error,
238
2
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
2
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
240
2
     "%s: data offset value out of bounds.",
241
2
     function );
242
243
2
    return( -1 );
244
2
  }
245
2.06k
  if( libfsntfs_index_node_header_initialize(
246
2.06k
       &( index_node->header ),
247
2.06k
       error ) != 1 )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
252
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
253
0
     "%s: unable to create index node header.",
254
0
     function );
255
256
0
    goto on_error;
257
0
  }
258
2.06k
  if( libfsntfs_index_node_header_read_data(
259
2.06k
       index_node->header,
260
2.06k
       &( data[ data_offset ] ),
261
2.06k
       data_size - data_offset,
262
2.06k
       error ) != 1 )
263
113
  {
264
113
    libcerror_error_set(
265
113
     error,
266
113
     LIBCERROR_ERROR_DOMAIN_IO,
267
113
     LIBCERROR_IO_ERROR_READ_FAILED,
268
113
     "%s: unable to read index node header.",
269
113
     function );
270
271
113
    goto on_error;
272
113
  }
273
1.95k
  index_node->header_data_offset = data_offset;
274
275
1.95k
  return( 1 );
276
277
113
on_error:
278
113
  if( index_node->header != NULL )
279
113
  {
280
113
    libfsntfs_index_node_header_free(
281
113
     &( index_node->header ),
282
113
     NULL );
283
113
  }
284
113
  return( -1 );
285
2.06k
}
286
287
/* Reads the index node values
288
 * Returns 1 if successful or -1 on error
289
 */
290
int libfsntfs_index_node_read_values(
291
     libfsntfs_index_node_t *index_node,
292
     off64_t index_value_vcn_offset,
293
     const uint8_t *data,
294
     size_t data_size,
295
     size_t data_offset,
296
     libcerror_error_t **error )
297
1.92k
{
298
1.92k
  libfsntfs_index_value_t *index_value = NULL;
299
1.92k
  static char *function                = "libfsntfs_index_node_read_values";
300
1.92k
  size_t index_node_size               = 0;
301
1.92k
  size_t index_values_offset           = 0;
302
1.92k
  size_t unknown_data_size             = 0;
303
1.92k
  ssize_t read_count                   = 0;
304
1.92k
  uint32_t index_value_flags           = 0;
305
1.92k
  int entry_index                      = 0;
306
1.92k
  int index_value_entry                = 0;
307
308
1.92k
  if( index_node == NULL )
309
0
  {
310
0
    libcerror_error_set(
311
0
     error,
312
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
313
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
314
0
     "%s: invalid index node.",
315
0
     function );
316
317
0
    return( -1 );
318
0
  }
319
1.92k
  if( index_node->header == NULL )
320
0
  {
321
0
    libcerror_error_set(
322
0
     error,
323
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
325
0
     "%s: invalid index node - missing header value.",
326
0
     function );
327
328
0
    return( -1 );
329
0
  }
330
1.92k
  if( data == NULL )
331
0
  {
332
0
    libcerror_error_set(
333
0
     error,
334
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
335
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
336
0
     "%s: invalid data.",
337
0
     function );
338
339
0
    return( -1 );
340
0
  }
341
1.92k
  if( data_size > (size_t) SSIZE_MAX )
342
0
  {
343
0
    libcerror_error_set(
344
0
     error,
345
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
346
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
347
0
     "%s: data size value exceeds maximum.",
348
0
     function );
349
350
0
    return( -1 );
351
0
  }
352
1.92k
  if( data_offset >= data_size )
353
9
  {
354
9
    libcerror_error_set(
355
9
     error,
356
9
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
357
9
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
358
9
     "%s: data offset value out of bounds.",
359
9
     function );
360
361
9
    return( -1 );
362
9
  }
363
1.91k
  index_values_offset = (size_t) index_node->header->index_values_offset;
364
365
1.91k
  if( index_values_offset > ( data_size - index_node->header_data_offset ) )
366
68
  {
367
68
    libcerror_error_set(
368
68
     error,
369
68
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
370
68
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
371
68
     "%s: invalid index values offset value out of bounds.",
372
68
     function );
373
374
68
    return( -1 );
375
68
  }
376
1.84k
  index_values_offset += index_node->header_data_offset;
377
378
1.84k
  index_node_size = index_node->header->size;
379
380
1.84k
  if( ( index_node_size < sizeof( fsntfs_index_node_header_t ) )
381
1.84k
   || ( index_node_size > data_size ) )
382
126
  {
383
126
    libcerror_error_set(
384
126
     error,
385
126
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
386
126
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
387
126
     "%s: invalid index node size value out of bounds.",
388
126
     function );
389
390
126
    goto on_error;
391
126
  }
392
1.72k
  index_node_size -= sizeof( fsntfs_index_node_header_t );
393
394
1.72k
  if( index_node_size == 0 )
395
159
  {
396
159
    return( 1 );
397
159
  }
398
1.56k
  if( data_offset < index_values_offset )
399
700
  {
400
700
    unknown_data_size = (size_t) index_values_offset - data_offset;
401
402
#if defined( HAVE_DEBUG_OUTPUT )
403
    if( libcnotify_verbose != 0 )
404
    {
405
      libcnotify_printf(
406
       "%s: unknown data:\n",
407
       function );
408
      libcnotify_print_data(
409
       &( data[ data_offset ] ),
410
       unknown_data_size,
411
       0 );
412
    }
413
#endif
414
700
    data_offset += unknown_data_size;
415
416
700
    if( unknown_data_size > index_node_size )
417
0
    {
418
0
      libcerror_error_set(
419
0
       error,
420
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
422
0
       "%s: invalid index values offset value out of bounds.",
423
0
       function );
424
425
0
      goto on_error;
426
0
    }
427
700
    index_node_size -= (uint32_t) unknown_data_size;
428
700
  }
429
9.20k
  while( index_node_size > 0 )
430
8.79k
  {
431
8.79k
    if( libfsntfs_index_value_initialize(
432
8.79k
         &index_value,
433
8.79k
         error ) != 1 )
434
0
    {
435
0
      libcerror_error_set(
436
0
       error,
437
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
438
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
439
0
       "%s: unable to create index value.",
440
0
       function );
441
442
0
      goto on_error;
443
0
    }
444
8.79k
    read_count = libfsntfs_index_value_read(
445
8.79k
                  index_value,
446
8.79k
                  index_value_vcn_offset + data_offset,
447
8.79k
                  &index_value_entry,
448
8.79k
                  data,
449
8.79k
                  data_size,
450
8.79k
                  data_offset,
451
8.79k
                  error );
452
453
8.79k
    if( read_count == -1 )
454
168
    {
455
168
      libcerror_error_set(
456
168
       error,
457
168
       LIBCERROR_ERROR_DOMAIN_IO,
458
168
       LIBCERROR_IO_ERROR_READ_FAILED,
459
168
       "%s: unable to read index value.",
460
168
       function );
461
462
168
      goto on_error;
463
168
    }
464
8.62k
    data_offset     += read_count;
465
8.62k
    index_node_size -= (uint32_t) read_count;
466
467
8.62k
    index_value_flags = index_value->flags;
468
469
8.62k
    if( libcdata_array_append_entry(
470
8.62k
         index_node->values_array,
471
8.62k
         &entry_index,
472
8.62k
         (intptr_t *) index_value,
473
8.62k
         error ) != 1 )
474
0
    {
475
0
      libcerror_error_set(
476
0
       error,
477
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
478
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
479
0
       "%s: unable to append index value to values array.",
480
0
       function );
481
482
0
      goto on_error;
483
0
    }
484
8.62k
    index_value = NULL;
485
486
8.62k
    if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 )
487
990
    {
488
990
      break;
489
990
    }
490
8.62k
  }
491
#if defined( HAVE_DEBUG_OUTPUT )
492
  if( index_node_size > 0 )
493
  {
494
    if( libcnotify_verbose != 0 )
495
    {
496
      libcnotify_printf(
497
       "%s: trailing data:\n",
498
       function );
499
      libcnotify_print_data(
500
       &( data[ data_offset ] ),
501
       (size_t) index_node_size,
502
       0 );
503
    }
504
    data_offset += index_node_size;
505
  }
506
#endif
507
1.39k
  return( 1 );
508
509
294
on_error:
510
294
  if( index_value != NULL )
511
168
  {
512
168
    libfsntfs_index_value_free(
513
168
     &index_value,
514
168
     NULL );
515
168
  }
516
294
  return( -1 );
517
1.56k
}
518
519
/* Retrieves the number of values
520
 * Returns 1 if successful or -1 on error
521
 */
522
int libfsntfs_index_node_get_number_of_values(
523
     libfsntfs_index_node_t *index_node,
524
     int *number_of_values,
525
     libcerror_error_t **error )
526
877
{
527
877
  static char *function = "libfsntfs_index_node_get_number_of_values";
528
529
877
  if( index_node == NULL )
530
0
  {
531
0
    libcerror_error_set(
532
0
     error,
533
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
534
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
535
0
     "%s: invalid index node.",
536
0
     function );
537
538
0
    return( -1 );
539
0
  }
540
877
  if( libcdata_array_get_number_of_entries(
541
877
       index_node->values_array,
542
877
       number_of_values,
543
877
       error ) != 1 )
544
0
  {
545
0
    libcerror_error_set(
546
0
     error,
547
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
548
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
549
0
     "%s: unable to retrieve number of entries from values array.",
550
0
     function );
551
552
0
    return( -1 );
553
0
  }
554
877
  return( 1 );
555
877
}
556
557
/* Retrieves a specific value
558
 * Returns 1 if successful or -1 on error
559
 */
560
int libfsntfs_index_node_get_value_by_index(
561
     libfsntfs_index_node_t *index_node,
562
     int value_entry,
563
     libfsntfs_index_value_t **value,
564
     libcerror_error_t **error )
565
4.59k
{
566
4.59k
  static char *function = "libfsntfs_index_node_get_value_by_index";
567
568
4.59k
  if( index_node == NULL )
569
0
  {
570
0
    libcerror_error_set(
571
0
     error,
572
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
573
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
574
0
     "%s: invalid index node.",
575
0
     function );
576
577
0
    return( -1 );
578
0
  }
579
4.59k
  if( libcdata_array_get_entry_by_index(
580
4.59k
       index_node->values_array,
581
4.59k
       value_entry,
582
4.59k
       (intptr_t **) value,
583
4.59k
       error ) != 1 )
584
0
  {
585
0
    libcerror_error_set(
586
0
     error,
587
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
588
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
589
0
     "%s: unable to retrieve entry: %d from values array.",
590
0
     function,
591
0
     value_entry );
592
593
0
    return( -1 );
594
0
  }
595
4.59k
  return( 1 );
596
4.59k
}
597