Coverage Report

Created: 2025-06-13 07:22

/src/libfsntfs/libfsntfs/libfsntfs_index_value.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Index value functions
3
 *
4
 * Copyright (C) 2010-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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfsntfs_debug.h"
28
#include "libfsntfs_definitions.h"
29
#include "libfsntfs_index_value.h"
30
#include "libfsntfs_libcerror.h"
31
#include "libfsntfs_libcnotify.h"
32
33
#include "fsntfs_index.h"
34
35
/* Creates an index value
36
 * Make sure the value index_value is referencing, is set to NULL
37
 * Returns 1 if successful or -1 on error
38
 */
39
int libfsntfs_index_value_initialize(
40
     libfsntfs_index_value_t **index_value,
41
     libcerror_error_t **error )
42
8.53k
{
43
8.53k
  static char *function = "libfsntfs_index_value_initialize";
44
45
8.53k
  if( index_value == NULL )
46
0
  {
47
0
    libcerror_error_set(
48
0
     error,
49
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51
0
     "%s: invalid index value.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
8.53k
  if( *index_value != NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
61
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62
0
     "%s: invalid index value value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
8.53k
  *index_value = memory_allocate_structure(
68
8.53k
                  libfsntfs_index_value_t );
69
70
8.53k
  if( *index_value == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
75
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
76
0
     "%s: unable to create index value.",
77
0
     function );
78
79
0
    goto on_error;
80
0
  }
81
8.53k
  if( memory_set(
82
8.53k
       *index_value,
83
8.53k
       0,
84
8.53k
       sizeof( libfsntfs_index_value_t ) ) == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
90
0
     "%s: unable to clear index value.",
91
0
     function );
92
93
0
    memory_free(
94
0
     *index_value );
95
96
0
    *index_value = NULL;
97
98
0
    return( -1 );
99
0
  }
100
8.53k
  return( 1 );
101
102
0
on_error:
103
0
  if( *index_value != NULL )
104
0
  {
105
0
    memory_free(
106
0
     *index_value );
107
108
0
    *index_value = NULL;
109
0
  }
110
0
  return( -1 );
111
8.53k
}
112
113
/* Frees an index value
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfsntfs_index_value_free(
117
     libfsntfs_index_value_t **index_value,
118
     libcerror_error_t **error )
119
8.53k
{
120
8.53k
  static char *function = "libfsntfs_index_value_free";
121
122
8.53k
  if( index_value == NULL )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
127
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
128
0
     "%s: invalid index value.",
129
0
     function );
130
131
0
    return( -1 );
132
0
  }
133
8.53k
  if( *index_value != NULL )
134
8.53k
  {
135
8.53k
    if( ( *index_value )->key_data != NULL )
136
6.47k
    {
137
6.47k
      memory_free(
138
6.47k
       ( *index_value )->key_data );
139
6.47k
    }
140
8.53k
    if( ( *index_value )->value_data != NULL )
141
5.57k
    {
142
5.57k
      memory_free(
143
5.57k
       ( *index_value )->value_data );
144
5.57k
    }
145
8.53k
    memory_free(
146
8.53k
     *index_value );
147
148
8.53k
    *index_value = NULL;
149
8.53k
  }
150
8.53k
  return( 1 );
151
8.53k
}
152
153
/* Reads the index value
154
 * Returns the number of bytes read if successful or -1 on error
155
 */
156
ssize_t libfsntfs_index_value_read(
157
         libfsntfs_index_value_t *index_value,
158
         off64_t index_value_vcn_offset,
159
         int *index_value_entry,
160
         const uint8_t *data,
161
         size_t data_size,
162
         size_t data_offset,
163
         libcerror_error_t **error )
164
8.53k
{
165
8.53k
  static char *function   = "libfsntfs_index_value_read";
166
8.53k
  uint32_t remaining_size = 0;
167
168
8.53k
  if( index_value == NULL )
169
0
  {
170
0
    libcerror_error_set(
171
0
     error,
172
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
173
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
174
0
     "%s: invalid index value.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
8.53k
  if( index_value_entry == NULL )
180
0
  {
181
0
    libcerror_error_set(
182
0
     error,
183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
184
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
185
0
     "%s: invalid index value entry.",
186
0
     function );
187
188
0
    return( -1 );
189
0
  }
190
8.53k
  if( data == NULL )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
195
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
196
0
     "%s: invalid data.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
8.53k
  if( data_size > (size_t) SSIZE_MAX )
202
0
  {
203
0
    libcerror_error_set(
204
0
     error,
205
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
206
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
207
0
     "%s: data size value exceeds maximum.",
208
0
     function );
209
210
0
    return( -1 );
211
0
  }
212
8.53k
  if( data_offset > (size_t) SSIZE_MAX )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
217
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
218
0
     "%s: data offset value exceeds maximum.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
8.53k
  if( data_offset >= data_size )
224
13
  {
225
13
    libcerror_error_set(
226
13
     error,
227
13
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
228
13
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
229
13
     "%s: data offset value out of bounds.",
230
13
     function );
231
232
13
    return( -1 );
233
13
  }
234
8.52k
  if( ( data_size < sizeof( fsntfs_index_value_t ) )
235
8.52k
   || ( data_offset > ( data_size - sizeof( fsntfs_index_value_t ) ) ) )
236
10
  {
237
10
    libcerror_error_set(
238
10
     error,
239
10
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
10
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
241
10
     "%s: data size value too small.",
242
10
     function );
243
244
10
    return( -1 );
245
10
  }
246
8.51k
  index_value->offset = index_value_vcn_offset;
247
248
#if defined( HAVE_DEBUG_OUTPUT )
249
  if( libcnotify_verbose != 0 )
250
  {
251
    libcnotify_printf(
252
     "%s: index value: %03d header data:\n",
253
     function,
254
     *index_value_entry );
255
    libcnotify_print_data(
256
     &( data[ data_offset ] ),
257
     sizeof( fsntfs_index_value_t ),
258
     0 );
259
  }
260
#endif
261
8.51k
  byte_stream_copy_to_uint64_little_endian(
262
8.51k
   ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->file_reference,
263
8.51k
   index_value->file_reference );
264
265
8.51k
  byte_stream_copy_to_uint16_little_endian(
266
8.51k
   ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->size,
267
8.51k
   index_value->size );
268
269
8.51k
  byte_stream_copy_to_uint16_little_endian(
270
8.51k
   ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->key_data_size,
271
8.51k
   index_value->key_data_size );
272
273
8.51k
  byte_stream_copy_to_uint32_little_endian(
274
8.51k
   ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->flags,
275
8.51k
   index_value->flags );
276
277
#if defined( HAVE_DEBUG_OUTPUT )
278
  if( libcnotify_verbose != 0 )
279
  {
280
    libcnotify_printf(
281
     "%s: index value: %03d file reference\t\t: %" PRIu64 "-%" PRIu64 "\n",
282
     function,
283
     *index_value_entry,
284
     index_value->file_reference & 0xffffffffffffUL,
285
     index_value->file_reference >> 48 );
286
287
    libcnotify_printf(
288
     "%s: index value: %03d offset\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
289
     function,
290
     *index_value_entry,
291
     index_value->offset,
292
     index_value->offset );
293
294
    libcnotify_printf(
295
     "%s: index value: %03d size\t\t\t: %" PRIu16 "\n",
296
     function,
297
     *index_value_entry,
298
     index_value->size );
299
300
    libcnotify_printf(
301
     "%s: index value: %03d key data size\t\t: %" PRIu16 "\n",
302
     function,
303
     *index_value_entry,
304
     index_value->key_data_size );
305
306
    libcnotify_printf(
307
     "%s: index value: %03d flags\t\t\t: 0x%08" PRIx32 "\n",
308
     function,
309
     *index_value_entry,
310
     index_value->flags );
311
    libfsntfs_debug_print_index_value_flags(
312
     index_value->flags );
313
    libcnotify_printf(
314
     "\n" );
315
  }
316
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
317
318
8.51k
  data_offset += sizeof( fsntfs_index_value_t );
319
320
8.51k
  if( ( (size_t) index_value->size < sizeof( fsntfs_index_value_t ) )
321
8.51k
   || ( (size_t) index_value->size > data_size ) )
322
67
  {
323
67
    libcerror_error_set(
324
67
     error,
325
67
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
326
67
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
327
67
     "%s: index value: %03d size exceeds data size.",
328
67
     function,
329
67
     *index_value_entry );
330
331
67
    goto on_error;
332
67
  }
333
8.44k
  remaining_size = (size_t) index_value->size - sizeof( fsntfs_index_value_t );
334
335
8.44k
  if( index_value->key_data_size > 0 )
336
6.51k
  {
337
6.51k
    if( (uint32_t) index_value->key_data_size > remaining_size )
338
23
    {
339
23
      libcerror_error_set(
340
23
       error,
341
23
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
23
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
343
23
       "%s: index value: %03d data size exceeds size.",
344
23
       function,
345
23
       *index_value_entry );
346
347
23
      goto on_error;
348
23
    }
349
6.49k
    index_value->key_data = (uint8_t *) memory_allocate(
350
6.49k
                                         sizeof( uint8_t ) * index_value->key_data_size );
351
352
6.49k
    if( index_value->key_data == NULL )
353
0
    {
354
0
      libcerror_error_set(
355
0
       error,
356
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
357
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
358
0
       "%s: unable to create index value: %03d key data.",
359
0
       function,
360
0
       *index_value_entry );
361
362
0
      goto on_error;
363
0
    }
364
6.49k
    if( data_offset > ( data_size - index_value->key_data_size ) )
365
10
    {
366
10
      libcerror_error_set(
367
10
       error,
368
10
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
369
10
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
370
10
       "%s: data size value too small.",
371
10
       function );
372
373
10
      goto on_error;
374
10
    }
375
6.48k
    if( memory_copy(
376
6.48k
         index_value->key_data,
377
6.48k
         &( data[ data_offset ] ),
378
6.48k
         (size_t) index_value->key_data_size ) == NULL )
379
0
    {
380
0
      libcerror_error_set(
381
0
       error,
382
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
383
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
384
0
       "%s: unable to copy index value: %03d data.",
385
0
       function,
386
0
       *index_value_entry );
387
388
0
      goto on_error;
389
0
    }
390
#if defined( HAVE_DEBUG_OUTPUT )
391
    if( libcnotify_verbose != 0 )
392
    {
393
      libcnotify_printf(
394
       "%s: index value: %03d key data:\n",
395
       function,
396
       *index_value_entry );
397
      libcnotify_print_data(
398
       &( data[ data_offset ] ),
399
       (size_t) index_value->key_data_size,
400
       0 );
401
    }
402
#endif
403
6.48k
    data_offset    += index_value->key_data_size;
404
6.48k
    remaining_size -= index_value->key_data_size;
405
6.48k
  }
406
8.41k
  if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
407
1.85k
  {
408
1.85k
    if( remaining_size < 8 )
409
8
    {
410
8
      libcerror_error_set(
411
8
       error,
412
8
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
413
8
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
414
8
       "%s: index value: %03d sub node data size exceeds size.",
415
8
       function,
416
8
       *index_value_entry );
417
418
8
      goto on_error;
419
8
    }
420
1.84k
    remaining_size -= 8;
421
1.84k
  }
422
8.40k
  if( remaining_size > 0 )
423
5.58k
  {
424
5.58k
    index_value->value_data = (uint8_t *) memory_allocate(
425
5.58k
                                           sizeof( uint8_t ) * remaining_size );
426
427
5.58k
    if( index_value->value_data == NULL )
428
0
    {
429
0
      libcerror_error_set(
430
0
       error,
431
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
432
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
433
0
       "%s: unable to create index value: %03d value data.",
434
0
       function,
435
0
       *index_value_entry );
436
437
0
      goto on_error;
438
0
    }
439
5.58k
    index_value->value_data_size = remaining_size;
440
441
5.58k
    if( data_offset > ( data_size - index_value->value_data_size ) )
442
8
    {
443
8
      libcerror_error_set(
444
8
       error,
445
8
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
446
8
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
447
8
       "%s: data size value too small.",
448
8
       function );
449
450
8
      goto on_error;
451
8
    }
452
5.57k
    if( memory_copy(
453
5.57k
         index_value->value_data,
454
5.57k
         &( data[ data_offset ] ),
455
5.57k
         (size_t) index_value->value_data_size ) == NULL )
456
0
    {
457
0
      libcerror_error_set(
458
0
       error,
459
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
460
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
461
0
       "%s: unable to copy index value: %03d data.",
462
0
       function,
463
0
       *index_value_entry );
464
465
0
      goto on_error;
466
0
    }
467
#if defined( HAVE_DEBUG_OUTPUT )
468
    if( libcnotify_verbose != 0 )
469
    {
470
      libcnotify_printf(
471
       "%s: index value: %03d value data:\n",
472
       function,
473
       *index_value_entry );
474
      libcnotify_print_data(
475
       index_value->value_data,
476
       (size_t) index_value->value_data_size,
477
       0 );
478
    }
479
#endif
480
5.57k
    data_offset += remaining_size;
481
5.57k
  }
482
8.39k
  if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
483
1.84k
  {
484
#if defined( HAVE_DEBUG_OUTPUT )
485
    if( libcnotify_verbose != 0 )
486
    {
487
      libcnotify_printf(
488
       "%s: index value: %03d sub node VCN data:\n",
489
       function,
490
       *index_value_entry );
491
      libcnotify_print_data(
492
       &( data[ data_offset ] ),
493
       8,
494
       0 );
495
    }
496
#endif
497
1.84k
    if( data_offset > ( data_size - 4 ) )
498
6
    {
499
6
      libcerror_error_set(
500
6
       error,
501
6
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
502
6
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
503
6
       "%s: data size value too small.",
504
6
       function );
505
506
6
      goto on_error;
507
6
    }
508
1.84k
    byte_stream_copy_to_uint32_little_endian(
509
1.84k
     &( data[ data_offset ] ),
510
1.84k
     index_value->sub_node_vcn );
511
512
#if defined( HAVE_DEBUG_OUTPUT )
513
    if( libcnotify_verbose != 0 )
514
    {
515
      libcnotify_printf(
516
       "%s: index value: %03d sub node VCN\t\t: %" PRIu64 "\n",
517
       function,
518
       *index_value_entry,
519
       index_value->sub_node_vcn );
520
521
      libcnotify_printf(
522
       "\n" );
523
    }
524
#endif
525
1.84k
  }
526
8.39k
  *index_value_entry += 1;
527
528
8.39k
  return( (ssize_t) index_value->size );
529
530
122
on_error:
531
122
  if( index_value->value_data != NULL )
532
11
  {
533
11
    memory_free(
534
11
     index_value->value_data );
535
536
11
    index_value->value_data = NULL;
537
11
  }
538
122
  index_value->value_data_size = 0;
539
540
122
  if( index_value->key_data != NULL )
541
21
  {
542
21
    memory_free(
543
21
     index_value->key_data );
544
545
21
    index_value->key_data = NULL;
546
21
  }
547
122
  index_value->key_data_size = 0;
548
549
122
  return( -1 );
550
8.39k
}
551