Coverage Report

Created: 2024-10-02 06:58

/src/libfshfs/libfshfs/libfshfs_attributes_btree_key.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The attributes B-tree key functions
3
 *
4
 * Copyright (C) 2009-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 "libfshfs_attributes_btree_key.h"
28
#include "libfshfs_debug.h"
29
#include "libfshfs_libcerror.h"
30
#include "libfshfs_libcnotify.h"
31
#include "libfshfs_libuna.h"
32
33
#include "fshfs_attributes_file.h"
34
35
/* Creates a attributes B-tree key
36
 * Make sure the value attributes_btree_key is referencing, is set to NULL
37
 * Returns 1 if successful or -1 on error
38
 */
39
int libfshfs_attributes_btree_key_initialize(
40
     libfshfs_attributes_btree_key_t **attributes_btree_key,
41
     libcerror_error_t **error )
42
6.32k
{
43
6.32k
  static char *function = "libfshfs_attributes_btree_key_initialize";
44
45
6.32k
  if( attributes_btree_key == 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 attributes B-tree key.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
6.32k
  if( *attributes_btree_key != 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 attributes B-tree key value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
6.32k
  *attributes_btree_key = memory_allocate_structure(
68
6.32k
                           libfshfs_attributes_btree_key_t );
69
70
6.32k
  if( *attributes_btree_key == 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 attributes B-tree key.",
77
0
     function );
78
79
0
    goto on_error;
80
0
  }
81
6.32k
  if( memory_set(
82
6.32k
       *attributes_btree_key,
83
6.32k
       0,
84
6.32k
       sizeof( libfshfs_attributes_btree_key_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 attributes B-tree key.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
6.32k
  return( 1 );
96
97
0
on_error:
98
0
  if( *attributes_btree_key != NULL )
99
0
  {
100
0
    memory_free(
101
0
     *attributes_btree_key );
102
103
0
    *attributes_btree_key = NULL;
104
0
  }
105
0
  return( -1 );
106
6.32k
}
107
108
/* Frees a attributes B-tree key
109
 * Returns 1 if successful or -1 on error
110
 */
111
int libfshfs_attributes_btree_key_free(
112
     libfshfs_attributes_btree_key_t **attributes_btree_key,
113
     libcerror_error_t **error )
114
6.32k
{
115
6.32k
  static char *function = "libfshfs_attributes_btree_key_free";
116
117
6.32k
  if( attributes_btree_key == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
122
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
123
0
     "%s: invalid attributes B-tree key.",
124
0
     function );
125
126
0
    return( -1 );
127
0
  }
128
6.32k
  if( *attributes_btree_key != NULL )
129
6.32k
  {
130
    /* The record_data reference is freed elsewhere
131
     */
132
6.32k
    memory_free(
133
6.32k
     *attributes_btree_key );
134
135
6.32k
    *attributes_btree_key = NULL;
136
6.32k
  }
137
6.32k
  return( 1 );
138
6.32k
}
139
140
/* Reads a attributes B-tree key
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfshfs_attributes_btree_key_read_data(
144
     libfshfs_attributes_btree_key_t *attributes_btree_key,
145
     const uint8_t *data,
146
     size_t data_size,
147
     libcerror_error_t **error )
148
6.32k
{
149
6.32k
  static char *function  = "libfshfs_attributes_btree_key_read_data";
150
6.32k
  uint16_t key_data_size = 0;
151
152
#if defined( HAVE_DEBUG_OUTPUT )
153
  uint32_t value_32bit   = 0;
154
  uint16_t value_16bit   = 0;
155
#endif
156
157
6.32k
  if( attributes_btree_key == NULL )
158
0
  {
159
0
    libcerror_error_set(
160
0
     error,
161
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
162
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
163
0
     "%s: invalid attributes B-tree key.",
164
0
     function );
165
166
0
    return( -1 );
167
0
  }
168
6.32k
  if( data == 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 data.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
6.32k
  if( ( data_size < 2 )
180
6.32k
   || ( data_size > SSIZE_MAX ) )
181
3
  {
182
3
    libcerror_error_set(
183
3
     error,
184
3
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
185
3
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
186
3
     "%s: invalid data size value out of bounds.",
187
3
     function );
188
189
3
    return( -1 );
190
3
  }
191
6.31k
  byte_stream_copy_to_uint16_big_endian(
192
6.31k
   ( (fshfs_attributes_index_key_hfsplus_t *) data )->data_size,
193
6.31k
   key_data_size );
194
195
6.31k
  if( (size_t) key_data_size > ( data_size - 2 ) )
196
20
  {
197
20
    libcerror_error_set(
198
20
     error,
199
20
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
200
20
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
201
20
     "%s: invalid key data size value out of bounds.",
202
20
     function );
203
204
20
    return( -1 );
205
20
  }
206
#if defined( HAVE_DEBUG_OUTPUT )
207
  if( libcnotify_verbose != 0 )
208
  {
209
    libcnotify_printf(
210
     "%s: key data:\n",
211
     function );
212
    libcnotify_print_data(
213
     data,
214
     (size_t) key_data_size + 2,
215
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
216
  }
217
#endif
218
#if defined( HAVE_DEBUG_OUTPUT )
219
  if( libcnotify_verbose != 0 )
220
  {
221
    libcnotify_printf(
222
     "%s: key data size\t\t\t: %" PRIu16 "\n",
223
     function,
224
     key_data_size );
225
  }
226
#endif
227
  /* The key data size can be 0 if the node is no longer used
228
   */
229
6.29k
  attributes_btree_key->data_size = key_data_size + 2;
230
231
6.29k
  if( key_data_size >= 14 )
232
2.63k
  {
233
2.63k
    byte_stream_copy_to_uint32_big_endian(
234
2.63k
     ( (fshfs_attributes_index_key_hfsplus_t *) data )->identifier,
235
2.63k
     attributes_btree_key->identifier );
236
237
2.63k
    byte_stream_copy_to_uint16_big_endian(
238
2.63k
     ( (fshfs_attributes_index_key_hfsplus_t *) data )->name_size,
239
2.63k
     attributes_btree_key->name_size );
240
241
#if defined( HAVE_DEBUG_OUTPUT )
242
    if( libcnotify_verbose != 0 )
243
    {
244
      byte_stream_copy_to_uint16_big_endian(
245
       ( (fshfs_attributes_index_key_hfsplus_t *) data )->unknown1,
246
       value_16bit );
247
      libcnotify_printf(
248
       "%s: unknown1\t\t\t: 0x%04" PRIx16 "\n",
249
       function,
250
       value_16bit );
251
252
      libcnotify_printf(
253
       "%s: identifier\t\t\t: %" PRIu32 "\n",
254
       function,
255
       attributes_btree_key->identifier );
256
257
      byte_stream_copy_to_uint32_big_endian(
258
       ( (fshfs_attributes_index_key_hfsplus_t *) data )->unknown2,
259
       value_32bit );
260
      libcnotify_printf(
261
       "%s: unknown2\t\t\t: 0x%08" PRIx32 "\n",
262
       function,
263
       value_32bit );
264
265
      libcnotify_printf(
266
       "%s: name number of characters\t: %" PRIu16 " (%" PRIu32 ")\n",
267
       function,
268
       attributes_btree_key->name_size,
269
       (uint32_t) attributes_btree_key->name_size * 2 );
270
    }
271
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
272
273
2.63k
    if( (uint32_t) attributes_btree_key->name_size > ( (uint32_t) UINT16_MAX / 2 ) )
274
43
    {
275
43
      libcerror_error_set(
276
43
       error,
277
43
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
278
43
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
279
43
       "%s: invalid attributes B-tree key - name size value out of bounds.",
280
43
       function );
281
282
43
      return( -1 );
283
43
    }
284
2.59k
    attributes_btree_key->name_size *= 2;
285
286
2.59k
    if( (size_t) attributes_btree_key->name_size > ( data_size - 14 ) )
287
46
    {
288
46
      libcerror_error_set(
289
46
       error,
290
46
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
291
46
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
292
46
       "%s: invalid attributes B-tree key - name size value out of bounds.",
293
46
       function );
294
295
46
      return( -1 );
296
46
    }
297
2.59k
  }
298
6.20k
  if( attributes_btree_key->name_size > 0 )
299
1.85k
  {
300
1.85k
    attributes_btree_key->name_data = &( data[ sizeof( fshfs_attributes_index_key_hfsplus_t ) ] );
301
302
#if defined( HAVE_DEBUG_OUTPUT )
303
    if( libcnotify_verbose != 0 )
304
    {
305
      if( libfshfs_debug_print_utf16_name_value(
306
           function,
307
           "name\t\t\t\t",
308
           attributes_btree_key->name_data,
309
           (size_t) attributes_btree_key->name_size,
310
           LIBUNA_ENDIAN_BIG,
311
           error ) != 1 )
312
      {
313
        libcerror_error_set(
314
         error,
315
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
316
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
317
         "%s: unable to print UTF-16 name value.",
318
         function );
319
320
        return( -1 );
321
      }
322
    }
323
#endif
324
1.85k
  }
325
#if defined( HAVE_DEBUG_OUTPUT )
326
  if( libcnotify_verbose != 0 )
327
  {
328
    libcnotify_printf(
329
     "\n" );
330
  }
331
#endif
332
6.20k
  attributes_btree_key->record_data      = &( data[ attributes_btree_key->data_size ] );
333
6.20k
  attributes_btree_key->record_data_size = data_size - attributes_btree_key->data_size;
334
335
6.20k
  return( 1 );
336
6.29k
}
337
338
/* Compares an UTF-8 string with the attributes B-tree key name
339
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
340
 */
341
int libfshfs_attributes_btree_key_compare_name_with_utf8_string(
342
     libfshfs_attributes_btree_key_t *attributes_btree_key,
343
     const uint8_t *utf8_string,
344
     size_t utf8_string_length,
345
     libcerror_error_t **error )
346
0
{
347
0
  static char *function = "libfshfs_attributes_btree_key_compare_name_with_utf8_string";
348
0
  int result            = 0;
349
350
0
  if( attributes_btree_key == 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 attributes B-tree key.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
  result = libuna_utf8_string_compare_with_utf16_stream(
362
0
            utf8_string,
363
0
            utf8_string_length,
364
0
            attributes_btree_key->name_data,
365
0
            attributes_btree_key->name_size,
366
0
            LIBUNA_ENDIAN_BIG,
367
0
            error );
368
369
0
  if( result == -1 )
370
0
  {
371
0
    libcerror_error_set(
372
0
     error,
373
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
374
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
375
0
     "%s: unable to compare UTF-8 string with name.",
376
0
     function );
377
378
0
    return( -1 );
379
0
  }
380
0
  return( result );
381
0
}
382
383
/* Compares an UTF-16 string with the attributes B-tree key name
384
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
385
 */
386
int libfshfs_attributes_btree_key_compare_name_with_utf16_string(
387
     libfshfs_attributes_btree_key_t *attributes_btree_key,
388
     const uint16_t *utf16_string,
389
     size_t utf16_string_length,
390
     libcerror_error_t **error )
391
0
{
392
0
  static char *function = "libfshfs_attributes_btree_key_compare_name_with_utf16_string";
393
0
  int result            = 0;
394
395
0
  if( attributes_btree_key == NULL )
396
0
  {
397
0
    libcerror_error_set(
398
0
     error,
399
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
400
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
401
0
     "%s: invalid attributes B-tree key.",
402
0
     function );
403
404
0
    return( -1 );
405
0
  }
406
0
  result = libuna_utf16_string_compare_with_utf16_stream(
407
0
            utf16_string,
408
0
            utf16_string_length,
409
0
            attributes_btree_key->name_data,
410
0
            attributes_btree_key->name_size,
411
0
            LIBUNA_ENDIAN_BIG,
412
0
            error );
413
414
0
  if( result == -1 )
415
0
  {
416
0
    libcerror_error_set(
417
0
     error,
418
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
419
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
420
0
     "%s: unable to compare UTF-16 string with name.",
421
0
     function );
422
423
0
    return( -1 );
424
0
  }
425
0
  return( result );
426
0
}
427