Coverage Report

Created: 2025-06-13 07:22

/src/libfwps/libfwps/libfwps_store.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Windows Serialized Property Store functions
3
 *
4
 * Copyright (C) 2013-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 "libfwps_libcdata.h"
28
#include "libfwps_libcerror.h"
29
#include "libfwps_libcnotify.h"
30
#include "libfwps_set.h"
31
#include "libfwps_store.h"
32
#include "libfwps_types.h"
33
34
/* Creates a store
35
 * Make sure the value store is referencing, is set to NULL
36
 * Returns 1 if successful or -1 on error
37
 */
38
int libfwps_store_initialize(
39
     libfwps_store_t **store,
40
     libcerror_error_t **error )
41
1.37k
{
42
1.37k
  libfwps_internal_store_t *internal_store = NULL;
43
1.37k
  static char *function                    = "libfwps_store_initialize";
44
45
1.37k
  if( store == 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 store.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
1.37k
  if( *store != 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 store value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
1.37k
  internal_store = memory_allocate_structure(
68
1.37k
                    libfwps_internal_store_t );
69
70
1.37k
  if( internal_store == 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 store.",
77
0
     function );
78
79
0
    goto on_error;
80
0
  }
81
1.37k
  if( memory_set(
82
1.37k
       internal_store,
83
1.37k
       0,
84
1.37k
       sizeof( libfwps_internal_store_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 store.",
91
0
     function );
92
93
0
    memory_free(
94
0
     internal_store );
95
96
0
    return( -1 );
97
0
  }
98
1.37k
  if( libcdata_array_initialize(
99
1.37k
       &( internal_store->sets_array ),
100
1.37k
       0,
101
1.37k
       error ) != 1 )
102
0
  {
103
0
    libcerror_error_set(
104
0
     error,
105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
106
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
107
0
     "%s: unable to create sets array.",
108
0
     function );
109
110
0
    goto on_error;
111
0
  }
112
1.37k
  *store = (libfwps_store_t *) internal_store;
113
114
1.37k
  return( 1 );
115
116
0
on_error:
117
0
  if( internal_store != NULL )
118
0
  {
119
0
    memory_free(
120
0
     internal_store );
121
0
  }
122
0
  return( -1 );
123
1.37k
}
124
125
/* Frees a store
126
 * Returns 1 if successful or -1 on error
127
 */
128
int libfwps_store_free(
129
     libfwps_store_t **store,
130
     libcerror_error_t **error )
131
1.37k
{
132
1.37k
  libfwps_internal_store_t *internal_store = NULL;
133
1.37k
  static char *function                    = "libfwps_store_free";
134
1.37k
  int result                               = 1;
135
136
1.37k
  if( store == NULL )
137
0
  {
138
0
    libcerror_error_set(
139
0
     error,
140
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
141
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
142
0
     "%s: invalid store.",
143
0
     function );
144
145
0
    return( -1 );
146
0
  }
147
1.37k
  if( *store != NULL )
148
1.37k
  {
149
1.37k
    internal_store = (libfwps_internal_store_t *) *store;
150
1.37k
    *store         = NULL;
151
152
1.37k
    if( libcdata_array_free(
153
1.37k
         &( internal_store->sets_array ),
154
1.37k
         (int(*)(intptr_t **, libcerror_error_t **)) &libfwps_internal_set_free,
155
1.37k
         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 sets array.",
162
0
       function );
163
164
0
      result = -1;
165
0
    }
166
1.37k
    memory_free(
167
1.37k
     internal_store );
168
1.37k
  }
169
1.37k
  return( result );
170
1.37k
}
171
172
/* Copies a store from a byte stream
173
 * Returns 1 if successful or -1 on error
174
 */
175
int libfwps_store_copy_from_byte_stream(
176
     libfwps_store_t *store,
177
     const uint8_t *byte_stream,
178
     size_t byte_stream_size,
179
     int ascii_codepage,
180
     libcerror_error_t **error )
181
1.37k
{
182
1.37k
  libfwps_internal_store_t *internal_store = NULL;
183
1.37k
  libfwps_set_t *set                       = NULL;
184
1.37k
  static char *function                    = "libfwps_store_copy_from_byte_stream";
185
1.37k
  size_t byte_stream_offset                = 0;
186
1.37k
  uint32_t set_data_size                   = 0;
187
1.37k
  int entry_index                          = 0;
188
1.37k
  int set_index                            = 0;
189
190
1.37k
  if( store == 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 store.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
1.37k
  internal_store = (libfwps_internal_store_t *) store;
202
203
1.37k
  if( byte_stream == NULL )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
209
0
     "%s: invalid byte stream.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
1.37k
  if( ( byte_stream_size < 4 )
215
1.37k
   || ( byte_stream_size > (size_t) SSIZE_MAX ) )
216
2
  {
217
2
    libcerror_error_set(
218
2
     error,
219
2
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220
2
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
221
2
     "%s: invalid byte stream size value out of bounds.",
222
2
     function );
223
224
2
    return( -1 );
225
2
  }
226
314k
  while( byte_stream_offset < byte_stream_size )
227
314k
  {
228
314k
    if( byte_stream_offset > ( byte_stream_size - 4 ) )
229
37
    {
230
37
      libcerror_error_set(
231
37
       error,
232
37
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
233
37
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
234
37
       "%s: invalid byte stream size value too small.",
235
37
       function );
236
237
37
      goto on_error;
238
37
    }
239
314k
    byte_stream_copy_to_uint32_little_endian(
240
314k
     &( byte_stream[ byte_stream_offset ] ),
241
314k
     set_data_size );
242
243
#if defined( HAVE_DEBUG_OUTPUT )
244
    if( libcnotify_verbose != 0 )
245
    {
246
      libcnotify_printf(
247
       "%s: set: %d data size\t\t\t: %" PRIu32 "\n",
248
       function,
249
       set_index,
250
       set_data_size );
251
    }
252
#endif
253
314k
    if( set_data_size == 0 )
254
12
    {
255
12
      break;
256
12
    }
257
314k
    if( ( set_data_size > byte_stream_size )
258
314k
     || ( byte_stream_offset > ( byte_stream_size - set_data_size ) ) )
259
135
    {
260
135
      libcerror_error_set(
261
135
       error,
262
135
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
263
135
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
264
135
       "%s: invalid set: %d data size value out of bounds.",
265
135
       function,
266
135
       set_index );
267
268
135
      goto on_error;
269
135
    }
270
314k
    if( libfwps_set_initialize(
271
314k
         &set,
272
314k
         error ) != 1 )
273
0
    {
274
0
      libcerror_error_set(
275
0
       error,
276
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
277
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
278
0
       "%s: unable to create set: %d.",
279
0
       function,
280
0
       set_index );
281
282
0
      goto on_error;
283
0
    }
284
314k
    ( (libfwps_internal_set_t *) set )->is_managed = 1;
285
286
314k
    if( libfwps_set_copy_from_byte_stream(
287
314k
         set,
288
314k
         &( byte_stream[ byte_stream_offset ] ),
289
314k
         (size_t) set_data_size,
290
314k
         ascii_codepage,
291
314k
         error ) != 1 )
292
771
    {
293
771
      libcerror_error_set(
294
771
       error,
295
771
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
771
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
297
771
       "%s: unable to copy set: %d from byte stream.",
298
771
       function,
299
771
       set_index );
300
301
771
      goto on_error;
302
771
    }
303
313k
    if( libcdata_array_append_entry(
304
313k
         internal_store->sets_array,
305
313k
         &entry_index,
306
313k
         (intptr_t *) set,
307
313k
         error ) != 1 )
308
0
    {
309
0
      libcerror_error_set(
310
0
       error,
311
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
312
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
313
0
       "%s: unable to append set: %d to array.",
314
0
       function,
315
0
       set_index );
316
317
0
      goto on_error;
318
0
    }
319
313k
    set = NULL;
320
321
313k
    byte_stream_offset += set_data_size;
322
323
313k
    set_index++;
324
313k
  }
325
433
  return( 1 );
326
327
943
on_error:
328
943
  if( set != NULL )
329
771
  {
330
771
    libfwps_internal_set_free(
331
771
     (libfwps_internal_set_t **) &set,
332
771
     NULL );
333
771
  }
334
943
  libcdata_array_empty(
335
943
   internal_store->sets_array,
336
943
   (int(*)(intptr_t **, libcerror_error_t **)) &libfwps_internal_set_free,
337
943
   NULL );
338
339
943
  return( -1 );
340
1.37k
}
341
342
/* Retrieves the number of sets
343
 * Returns 1 if successful or -1 on error
344
 */
345
int libfwps_store_get_number_of_sets(
346
     libfwps_store_t *store,
347
     int *number_of_sets,
348
     libcerror_error_t **error )
349
0
{
350
0
  libfwps_internal_store_t *internal_store = NULL;
351
0
  static char *function                    = "libfwps_store_get_number_of_sets";
352
353
0
  if( store == NULL )
354
0
  {
355
0
    libcerror_error_set(
356
0
     error,
357
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
358
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
359
0
     "%s: invalid store.",
360
0
     function );
361
362
0
    return( -1 );
363
0
  }
364
0
  internal_store = (libfwps_internal_store_t *) store;
365
366
0
  if( libcdata_array_get_number_of_entries(
367
0
       internal_store->sets_array,
368
0
       number_of_sets,
369
0
       error ) != 1 )
370
0
  {
371
0
    libcerror_error_set(
372
0
     error,
373
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
374
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
375
0
     "%s: unable to retrieve number of sets.",
376
0
     function );
377
378
0
    return( -1 );
379
0
  }
380
0
  return( 1 );
381
0
}
382
383
/* Retrieves a specific set
384
 * Returns 1 if successful or -1 on error
385
 */
386
int libfwps_store_get_set_by_index(
387
     libfwps_store_t *store,
388
     int set_index,
389
     libfwps_set_t **set,
390
     libcerror_error_t **error )
391
0
{
392
0
  libfwps_internal_store_t *internal_store = NULL;
393
0
  static char *function                    = "libfwps_store_get_set_by_index";
394
395
0
  if( store == 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 store.",
402
0
     function );
403
404
0
    return( -1 );
405
0
  }
406
0
  internal_store = (libfwps_internal_store_t *) store;
407
408
0
  if( libcdata_array_get_entry_by_index(
409
0
       internal_store->sets_array,
410
0
       set_index,
411
0
       (intptr_t **) set,
412
0
       error ) != 1 )
413
0
  {
414
0
    libcerror_error_set(
415
0
     error,
416
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
417
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
418
0
     "%s: unable to retrieve set: %d.",
419
0
     function,
420
0
     set_index );
421
422
0
    return( -1 );
423
0
  }
424
0
  return( 1 );
425
0
}
426