Coverage Report

Created: 2026-07-25 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfwevt/libfwevt/libfwevt_level.c
Line
Count
Source
1
/*
2
 * Level functions
3
 *
4
 * Copyright (C) 2011-2026, 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 <narrow_string.h>
26
#include <system_string.h>
27
#include <types.h>
28
#include <wide_string.h>
29
30
#include "libfwevt_debug.h"
31
#include "libfwevt_level.h"
32
#include "libfwevt_libcerror.h"
33
#include "libfwevt_libcnotify.h"
34
#include "libfwevt_libuna.h"
35
#include "libfwevt_types.h"
36
37
#include "fwevt_template.h"
38
39
/* Creates a level
40
 * Make sure the value level is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfwevt_level_initialize(
44
     libfwevt_level_t **level,
45
     libcerror_error_t **error )
46
33.8k
{
47
33.8k
  libfwevt_internal_level_t *internal_level = NULL;
48
33.8k
  static char *function                     = "libfwevt_level_initialize";
49
50
33.8k
  if( level == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid level.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
33.8k
  if( *level != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid level value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
33.8k
  internal_level = memory_allocate_structure(
73
33.8k
                    libfwevt_internal_level_t );
74
75
33.8k
  if( internal_level == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create level.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
33.8k
  if( memory_set(
87
33.8k
       internal_level,
88
33.8k
       0,
89
33.8k
       sizeof( libfwevt_internal_level_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear level.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
33.8k
  *level = (libfwevt_level_t *) internal_level;
101
102
33.8k
  return( 1 );
103
104
0
on_error:
105
0
  if( internal_level != NULL )
106
0
  {
107
0
    memory_free(
108
0
     internal_level );
109
0
  }
110
0
  return( -1 );
111
33.8k
}
112
113
/* Frees a level
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfwevt_level_free(
117
     libfwevt_level_t **level,
118
     libcerror_error_t **error )
119
0
{
120
0
  static char *function = "libfwevt_level_free";
121
122
0
  if( level == 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 level.",
129
0
     function );
130
131
0
    return( -1 );
132
0
  }
133
0
  if( *level != NULL )
134
0
  {
135
0
    *level = NULL;
136
0
  }
137
0
  return( 1 );
138
0
}
139
140
/* Frees a level
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfwevt_internal_level_free(
144
     libfwevt_internal_level_t **internal_level,
145
     libcerror_error_t **error )
146
33.8k
{
147
33.8k
  static char *function = "libfwevt_internal_level_free";
148
149
33.8k
  if( internal_level == NULL )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155
0
     "%s: invalid level.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
33.8k
  if( *internal_level != NULL )
161
33.8k
  {
162
33.8k
    memory_free(
163
33.8k
     *internal_level );
164
165
33.8k
    *internal_level = NULL;
166
33.8k
  }
167
33.8k
  return( 1 );
168
33.8k
}
169
170
/* Reads the level
171
 * Returns 1 if successful or -1 on error
172
 */
173
int libfwevt_level_read_data(
174
     libfwevt_level_t *level,
175
     const uint8_t *data,
176
     size_t data_size,
177
     size_t data_offset,
178
     libcerror_error_t **error )
179
33.8k
{
180
33.8k
  fwevt_template_level_t *wevt_level = NULL;
181
33.8k
  static char *function              = "libfwevt_level_read_data";
182
33.8k
  uint32_t level_data_offset         = 0;
183
33.8k
  uint32_t level_data_size           = 0;
184
185
#if defined( HAVE_DEBUG_OUTPUT )
186
  uint32_t value_32bit               = 0;
187
#endif
188
189
33.8k
  if( level == NULL )
190
0
  {
191
0
    libcerror_error_set(
192
0
     error,
193
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
194
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
195
0
     "%s: invalid level.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
33.8k
  if( data == NULL )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
205
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
206
0
     "%s: invalid data.",
207
0
     function );
208
209
0
    return( -1 );
210
0
  }
211
33.8k
  if( data_size > (size_t) SSIZE_MAX )
212
0
  {
213
0
    libcerror_error_set(
214
0
     error,
215
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
216
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
217
0
     "%s: invalid data size value exceeds maximum.",
218
0
     function );
219
220
0
    return( -1 );
221
0
  }
222
33.8k
  if( data_offset >= data_size )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
227
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
228
0
     "%s: invalid data offset value out of bounds.",
229
0
     function );
230
231
0
    return( -1 );
232
0
  }
233
33.8k
  if( ( data_size < sizeof( fwevt_template_level_t ) )
234
33.8k
   || ( data_offset > ( data_size - sizeof( fwevt_template_level_t ) ) ) )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
240
0
     "%s: invalid data value too small.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
33.8k
  wevt_level = (fwevt_template_level_t *) &( data[ data_offset ] );
246
247
#if defined( HAVE_DEBUG_OUTPUT )
248
  if( libcnotify_verbose != 0 )
249
  {
250
    libcnotify_printf(
251
     "%s: level data:\n",
252
     function );
253
    libcnotify_print_data(
254
     (uint8_t *) wevt_level,
255
     sizeof( fwevt_template_level_t ),
256
     0 );
257
  }
258
#endif
259
33.8k
  byte_stream_copy_to_uint32_little_endian(
260
33.8k
   wevt_level->data_offset,
261
33.8k
   level_data_offset );
262
263
#if defined( HAVE_DEBUG_OUTPUT )
264
  if( libcnotify_verbose != 0 )
265
  {
266
    byte_stream_copy_to_uint32_little_endian(
267
     wevt_level->identifier,
268
     value_32bit );
269
    libcnotify_printf(
270
     "%s: identifier\t\t\t\t\t: %" PRIu32 "\n",
271
     function,
272
     value_32bit );
273
274
    byte_stream_copy_to_uint32_little_endian(
275
     wevt_level->message_identifier,
276
     value_32bit );
277
    libcnotify_printf(
278
     "%s: message identifier\t\t\t\t: 0x%08" PRIx32 "\n",
279
     function,
280
     value_32bit );
281
282
    libcnotify_printf(
283
     "%s: data offset\t\t\t\t\t: 0x%08" PRIx32 "\n",
284
     function,
285
     level_data_offset );
286
  }
287
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
288
289
33.8k
  if( level_data_offset > 0 )
290
1.02k
  {
291
1.02k
    if( level_data_offset >= ( data_size - 4 ) )
292
103
    {
293
103
      libcerror_error_set(
294
103
       error,
295
103
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
103
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
297
103
       "%s: invalid level data offset value out of bounds.",
298
103
       function );
299
300
103
      return( -1 );
301
103
    }
302
923
    byte_stream_copy_to_uint32_little_endian(
303
923
     &( data[ level_data_offset ] ),
304
923
     level_data_size );
305
306
923
    if( ( data_size < level_data_size )
307
865
     || ( level_data_offset > ( data_size - level_data_size ) ) )
308
66
    {
309
66
      libcerror_error_set(
310
66
       error,
311
66
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
312
66
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
313
66
       "%s: invalid level data size value out of bounds.",
314
66
       function );
315
316
66
      return( -1 );
317
66
    }
318
#if defined( HAVE_DEBUG_OUTPUT )
319
    if( libcnotify_verbose != 0 )
320
    {
321
      libcnotify_printf(
322
       "%s: data:\n",
323
       function );
324
      libcnotify_print_data(
325
       &( data[ level_data_offset ] ),
326
       level_data_size,
327
       0 );
328
    }
329
#endif
330
#if defined( HAVE_DEBUG_OUTPUT )
331
    if( libcnotify_verbose != 0 )
332
    {
333
      libcnotify_printf(
334
       "%s: data size\t\t\t\t\t: %" PRIu32 "\n",
335
       function,
336
       level_data_size );
337
338
      if( level_data_size >= 4 )
339
      {
340
        level_data_offset += 4;
341
        level_data_size   -= 4;
342
343
        if( libfwevt_debug_print_utf16_string_value(
344
             function,
345
             "name\t\t\t\t\t\t",
346
             &( data[ level_data_offset ] ),
347
             level_data_size,
348
             LIBUNA_ENDIAN_LITTLE,
349
             error ) != 1 )
350
        {
351
          libcerror_error_set(
352
           error,
353
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
354
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
355
           "%s: unable to print UTF-16 string value.",
356
           function );
357
358
          return( -1 );
359
        }
360
      }
361
    }
362
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
363
923
  }
364
#if defined( HAVE_DEBUG_OUTPUT )
365
  if( libcnotify_verbose != 0 )
366
  {
367
    libcnotify_printf(
368
     "\n" );
369
  }
370
#endif
371
33.6k
  return( 1 );
372
33.8k
}
373