Coverage Report

Created: 2025-06-13 07:22

/src/libesedb/libesedb/libesedb_data_segment.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Data segment 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 <memory.h>
24
#include <types.h>
25
26
#include "libesedb_data_segment.h"
27
#include "libesedb_libbfio.h"
28
#include "libesedb_libcerror.h"
29
#include "libesedb_libcnotify.h"
30
#include "libesedb_libfdata.h"
31
#include "libesedb_unused.h"
32
33
/* Creates a data segment
34
 * Make sure the value data_segment is referencing, is set to NULL
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libesedb_data_segment_initialize(
38
     libesedb_data_segment_t **data_segment,
39
     size_t data_size,
40
     libcerror_error_t **error )
41
0
{
42
0
  static char *function = "libesedb_data_segment_initialize";
43
44
0
  if( data_segment == NULL )
45
0
  {
46
0
    libcerror_error_set(
47
0
     error,
48
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50
0
     "%s: invalid data segment.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
0
  if( *data_segment != NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61
0
     "%s: invalid data segment value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
0
  if( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
72
0
     "%s: invalid data size value exceeds maximum allocation size.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
0
  *data_segment = memory_allocate_structure(
78
0
                   libesedb_data_segment_t );
79
80
0
  if( *data_segment == NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
85
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86
0
     "%s: unable to create data segment.",
87
0
     function );
88
89
0
    goto on_error;
90
0
  }
91
0
  if( memory_set(
92
0
       *data_segment,
93
0
       0,
94
0
       sizeof( libesedb_data_segment_t ) ) == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
100
0
     "%s: unable to clear data segment.",
101
0
     function );
102
103
0
    memory_free(
104
0
     *data_segment );
105
106
0
    *data_segment = NULL;
107
108
0
    return( -1 );
109
0
  }
110
0
  if( data_size > 0 )
111
0
  {
112
0
    ( *data_segment )->data = (uint8_t *) memory_allocate(
113
0
                                           sizeof( uint8_t ) * data_size );
114
115
0
    if( ( *data_segment )->data == NULL )
116
0
    {
117
0
      libcerror_error_set(
118
0
       error,
119
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
120
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
121
0
       "%s: unable to create data.",
122
0
       function );
123
124
0
      goto on_error;
125
0
    }
126
0
    ( *data_segment )->data_size = data_size;
127
0
  }
128
0
  return( 1 );
129
130
0
on_error:
131
0
  if( *data_segment != NULL )
132
0
  {
133
0
    memory_free(
134
0
     *data_segment );
135
136
0
    *data_segment = NULL;
137
0
  }
138
0
  return( -1 );
139
0
}
140
141
/* Frees a data segment
142
 * Returns 1 if successful or -1 on error
143
 */
144
int libesedb_data_segment_free(
145
     libesedb_data_segment_t **data_segment,
146
     libcerror_error_t **error )
147
0
{
148
0
  static char *function = "libesedb_data_segment_free";
149
150
0
  if( data_segment == NULL )
151
0
  {
152
0
    libcerror_error_set(
153
0
     error,
154
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
155
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
156
0
     "%s: invalid data segment.",
157
0
     function );
158
159
0
    return( -1 );
160
0
  }
161
0
  if( *data_segment != NULL )
162
0
  {
163
0
    if( ( *data_segment )->data != NULL )
164
0
    {
165
0
      memory_free(
166
0
       ( *data_segment )->data );
167
0
    }
168
0
    memory_free(
169
0
     *data_segment );
170
171
0
    *data_segment = NULL;
172
0
  }
173
0
  return( 1 );
174
0
}
175
176
/* Retrieves the data size
177
 * Returns 1 if successful or -1 on error
178
 */
179
int libesedb_data_segment_get_data_size(
180
     libesedb_data_segment_t *data_segment,
181
     size_t *data_size,
182
     libcerror_error_t **error )
183
0
{
184
0
  static char *function = "libesedb_data_segment_get_data_size";
185
186
0
  if( data_segment == NULL )
187
0
  {
188
0
    libcerror_error_set(
189
0
     error,
190
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
191
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
192
0
     "%s: invalid data segment.",
193
0
     function );
194
195
0
    return( -1 );
196
0
  }
197
0
  if( data_size == NULL )
198
0
  {
199
0
    libcerror_error_set(
200
0
     error,
201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
203
0
     "%s: invalid data size.",
204
0
     function );
205
206
0
    return( -1 );
207
0
  }
208
0
  *data_size = data_segment->data_size;
209
210
0
  return( 1 );
211
0
}
212
213
/* Retrieves the data
214
 * Returns 1 if successful or -1 on error
215
 */
216
int libesedb_data_segment_get_data(
217
     libesedb_data_segment_t *data_segment,
218
     uint8_t *data,
219
     size_t data_size,
220
     libcerror_error_t **error )
221
0
{
222
0
  static char *function = "libesedb_data_segment_get_data";
223
224
0
  if( data_segment == NULL )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
229
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
230
0
     "%s: invalid data segment.",
231
0
     function );
232
233
0
    return( -1 );
234
0
  }
235
0
  if( data == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241
0
     "%s: invalid data.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
0
  if( data_size > (size_t) SSIZE_MAX )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
252
0
     "%s: invalid data size value exceeds maximum.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
0
  if( data_size < data_segment->data_size )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
263
0
     "%s: data size value too small.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
0
  if( memory_copy(
269
0
       data,
270
0
       data_segment->data,
271
0
       data_segment->data_size ) == NULL )
272
0
  {
273
0
    libcerror_error_set(
274
0
     error,
275
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
276
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
277
0
     "%s: unable to copy data.",
278
0
     function );
279
280
0
    return( -1 );
281
0
  }
282
0
  return( 1 );
283
0
}
284
285
/* Reads a data segment
286
 * Callback for the data segments list
287
 * Returns 1 if successful or -1 on error
288
 */
289
int libesedb_data_segment_read_element_data(
290
     intptr_t *data_handle LIBESEDB_ATTRIBUTE_UNUSED,
291
     libbfio_handle_t *file_io_handle,
292
     libfdata_list_element_t *element,
293
     libfdata_cache_t *cache,
294
     int element_file_index LIBESEDB_ATTRIBUTE_UNUSED,
295
     off64_t element_offset,
296
     size64_t element_size,
297
     uint32_t element_flags LIBESEDB_ATTRIBUTE_UNUSED,
298
     uint8_t read_flags LIBESEDB_ATTRIBUTE_UNUSED,
299
     libcerror_error_t **error )
300
0
{
301
0
  libesedb_data_segment_t *data_segment = NULL;
302
0
  static char *function                 = "libesedb_data_segment_read_element_data";
303
0
  ssize_t read_count                    = 0;
304
305
0
  LIBESEDB_UNREFERENCED_PARAMETER( data_handle )
306
0
  LIBESEDB_UNREFERENCED_PARAMETER( element_file_index )
307
0
  LIBESEDB_UNREFERENCED_PARAMETER( element_flags )
308
0
  LIBESEDB_UNREFERENCED_PARAMETER( read_flags )
309
310
0
  if( element_size > (size64_t) SSIZE_MAX )
311
0
  {
312
0
    libcerror_error_set(
313
0
     error,
314
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
316
0
     "%s: invalid element size value out of bounds.",
317
0
     function );
318
319
0
    return( -1 );
320
0
  }
321
0
  if( libesedb_data_segment_initialize(
322
0
       &data_segment,
323
0
       (size_t) element_size,
324
0
       error ) != 1 )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
330
0
     "%s: unable to create data segment.",
331
0
     function );
332
333
0
    goto on_error;
334
0
  }
335
#if defined( HAVE_DEBUG_OUTPUT )
336
  if( libcnotify_verbose != 0 )
337
  {
338
    libcnotify_printf(
339
     "%s: reading data segment at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
340
     function,
341
     element_offset,
342
     element_offset );
343
  }
344
#endif
345
0
  read_count = libbfio_handle_read_buffer_at_offset(
346
0
          file_io_handle,
347
0
          data_segment->data,
348
0
          data_segment->data_size,
349
0
          element_offset,
350
0
          error );
351
352
0
  if( read_count == -1 )
353
0
  {
354
0
    libcerror_error_set(
355
0
     error,
356
0
     LIBCERROR_ERROR_DOMAIN_IO,
357
0
     LIBCERROR_IO_ERROR_READ_FAILED,
358
0
     "%s: unable to read data segment at offset: %" PRIi64 " (0x%08" PRIx64 ").",
359
0
     function,
360
0
     element_offset,
361
0
     element_offset );
362
363
0
    goto on_error;
364
0
  }
365
0
  if( libfdata_list_element_set_element_value(
366
0
       element,
367
0
       (intptr_t *) file_io_handle,
368
0
       cache,
369
0
       (intptr_t *) data_segment,
370
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_data_segment_free,
371
0
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
372
0
       error ) != 1 )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
378
0
     "%s: unable to set data segment as element value.",
379
0
     function );
380
381
0
    goto on_error;
382
0
  }
383
0
  return( 1 );
384
385
0
on_error:
386
0
  if( data_segment != NULL )
387
0
  {
388
0
    libesedb_data_segment_free(
389
0
     &data_segment,
390
0
     NULL );
391
0
  }
392
0
  return( -1 );
393
0
}
394