Coverage Report

Created: 2025-06-13 07:22

/src/libfwevt/libfwevt/libfwevt_opcode.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Opcode functions
3
 *
4
 * Copyright (C) 2011-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 <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_libcerror.h"
32
#include "libfwevt_libcnotify.h"
33
#include "libfwevt_libuna.h"
34
#include "libfwevt_opcode.h"
35
#include "libfwevt_types.h"
36
37
#include "fwevt_template.h"
38
39
/* Creates an opcode
40
 * Make sure the value opcode is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfwevt_opcode_initialize(
44
     libfwevt_opcode_t **opcode,
45
     libcerror_error_t **error )
46
46.1k
{
47
46.1k
  libfwevt_internal_opcode_t *internal_opcode = NULL;
48
46.1k
  static char *function                       = "libfwevt_opcode_initialize";
49
50
46.1k
  if( opcode == 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 opcode.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
46.1k
  if( *opcode != 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 opcode value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
46.1k
  internal_opcode = memory_allocate_structure(
73
46.1k
                     libfwevt_internal_opcode_t );
74
75
46.1k
  if( internal_opcode == 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 opcode.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
46.1k
  if( memory_set(
87
46.1k
       internal_opcode,
88
46.1k
       0,
89
46.1k
       sizeof( libfwevt_internal_opcode_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 opcode.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
46.1k
  *opcode = (libfwevt_opcode_t *) internal_opcode;
101
102
46.1k
  return( 1 );
103
104
0
on_error:
105
0
  if( internal_opcode != NULL )
106
0
  {
107
0
    memory_free(
108
0
     internal_opcode );
109
0
  }
110
0
  return( -1 );
111
46.1k
}
112
113
/* Frees an opcode
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfwevt_opcode_free(
117
     libfwevt_opcode_t **opcode,
118
     libcerror_error_t **error )
119
0
{
120
0
  static char *function = "libfwevt_opcode_free";
121
122
0
  if( opcode == 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 opcode.",
129
0
     function );
130
131
0
    return( -1 );
132
0
  }
133
0
  if( *opcode != NULL )
134
0
  {
135
0
    *opcode = NULL;
136
0
  }
137
0
  return( 1 );
138
0
}
139
140
/* Frees an opcode
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfwevt_internal_opcode_free(
144
     libfwevt_internal_opcode_t **internal_opcode,
145
     libcerror_error_t **error )
146
46.1k
{
147
46.1k
  static char *function = "libfwevt_internal_opcode_free";
148
149
46.1k
  if( internal_opcode == 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 opcode.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
46.1k
  if( *internal_opcode != NULL )
161
46.1k
  {
162
46.1k
    memory_free(
163
46.1k
     *internal_opcode );
164
165
46.1k
    *internal_opcode = NULL;
166
46.1k
  }
167
46.1k
  return( 1 );
168
46.1k
}
169
170
/* Reads the opcode
171
 * Returns 1 if successful or -1 on error
172
 */
173
int libfwevt_opcode_read_data(
174
     libfwevt_opcode_t *opcode,
175
     const uint8_t *data,
176
     size_t data_size,
177
     size_t data_offset,
178
     libcerror_error_t **error )
179
46.1k
{
180
46.1k
  fwevt_template_opcode_t *wevt_opcode = NULL;
181
46.1k
  static char *function                = "libfwevt_opcode_read_data";
182
46.1k
  uint32_t opcode_data_offset          = 0;
183
46.1k
  uint32_t opcode_data_size            = 0;
184
185
#if defined( HAVE_DEBUG_OUTPUT )
186
  uint32_t value_32bit                 = 0;
187
#endif
188
189
46.1k
  if( opcode == 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 opcode.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
46.1k
  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
46.1k
  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
46.1k
  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
46.1k
  if( ( data_size < sizeof( fwevt_template_opcode_t ) )
234
46.1k
   || ( data_offset > ( data_size - sizeof( fwevt_template_opcode_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
46.1k
  wevt_opcode = (fwevt_template_opcode_t *) &( data[ data_offset ] );
246
247
#if defined( HAVE_DEBUG_OUTPUT )
248
  if( libcnotify_verbose != 0 )
249
  {
250
    libcnotify_printf(
251
     "%s: opcode data:\n",
252
     function );
253
    libcnotify_print_data(
254
     (uint8_t *) wevt_opcode,
255
     sizeof( fwevt_template_opcode_t ),
256
     0 );
257
  }
258
#endif
259
46.1k
  byte_stream_copy_to_uint32_little_endian(
260
46.1k
   wevt_opcode->data_offset,
261
46.1k
   opcode_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_opcode->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_opcode->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
     opcode_data_offset );
286
  }
287
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
288
289
46.1k
  if( opcode_data_offset > 0 )
290
740
  {
291
740
    if( opcode_data_offset >= ( data_size - 4 ) )
292
89
    {
293
89
      libcerror_error_set(
294
89
       error,
295
89
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
89
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
297
89
       "%s: invalid opcode data offset value out of bounds.",
298
89
       function );
299
300
89
      return( -1 );
301
89
    }
302
651
    byte_stream_copy_to_uint32_little_endian(
303
651
     &( data[ opcode_data_offset ] ),
304
651
     opcode_data_size );
305
306
651
    if( ( data_size < opcode_data_size )
307
651
     || ( opcode_data_offset > ( data_size - opcode_data_size ) ) )
308
65
    {
309
65
      libcerror_error_set(
310
65
       error,
311
65
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
312
65
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
313
65
       "%s: invalid opcode data size value out of bounds.",
314
65
       function );
315
316
65
      return( -1 );
317
65
    }
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[ opcode_data_offset ] ),
326
       opcode_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
       opcode_data_size );
337
    }
338
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
339
340
586
    if( opcode_data_size >= 4 )
341
305
    {
342
305
      opcode_data_offset += 4;
343
305
      opcode_data_size   -= 4;
344
345
#if defined( HAVE_DEBUG_OUTPUT )
346
      if( libcnotify_verbose != 0 )
347
      {
348
        if( libfwevt_debug_print_utf16_string_value(
349
             function,
350
             "name\t\t\t\t\t\t",
351
             &( data[ opcode_data_offset ] ),
352
             opcode_data_size,
353
             LIBUNA_ENDIAN_LITTLE,
354
             error ) != 1 )
355
        {
356
          libcerror_error_set(
357
           error,
358
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
359
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
360
           "%s: unable to print UTF-16 string value.",
361
           function );
362
363
          return( -1 );
364
        }
365
      }
366
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
367
305
    }
368
586
  }
369
#if defined( HAVE_DEBUG_OUTPUT )
370
  if( libcnotify_verbose != 0 )
371
  {
372
    libcnotify_printf(
373
     "\n" );
374
  }
375
#endif
376
46.0k
  return( 1 );
377
46.1k
}
378