Coverage Report

Created: 2025-06-13 07:22

/src/libevtx/libfwevt/libfwevt_xml_string.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * XML string 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 <types.h>
24
25
#include "libfwevt_libcerror.h"
26
#include "libfwevt_libuna.h"
27
#include "libfwevt_xml_string.h"
28
29
/* Determines the size of an UTF-8 XML string from an UTF-16 stream
30
 * Returns 1 if successful or -1 on error
31
 */
32
int libfwevt_utf8_xml_string_size_from_utf16_stream(
33
     const uint8_t *utf16_stream,
34
     size_t utf16_stream_size,
35
     int byte_order,
36
     size_t *utf8_string_size,
37
     libcerror_error_t **error )
38
0
{
39
0
  static char *function                        = "libfwevt_utf8_xml_string_size_from_utf16_stream";
40
0
  libuna_unicode_character_t unicode_character = 0;
41
0
  size_t safe_utf8_string_size                 = 0;
42
0
  size_t utf16_stream_index                    = 0;
43
0
  int read_byte_order                          = 0;
44
0
  int result                                   = 0;
45
46
0
  if( utf16_stream == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid UTF-16 stream.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
0
  if( utf16_stream_size > (size_t) SSIZE_MAX )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
63
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  if( ( utf16_stream_size % 2 ) != 0 )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
74
0
     "%s: missing UTF-16 stream value.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
0
  if( utf8_string_size == NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
84
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
85
0
     "%s: invalid UTF-8 string size.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
0
  if( utf16_stream_size == 0 )
91
0
  {
92
0
    return( 1 );
93
0
  }
94
  /* Check if UTF-16 stream is in big or little endian
95
   */
96
0
  if( utf16_stream_size >= 2 )
97
0
  {
98
0
    if( ( utf16_stream[ 0 ] == 0xfe )
99
0
     && ( utf16_stream[ 1 ] == 0xff ) )
100
0
    {
101
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
102
0
      utf16_stream_index = 2;
103
0
    }
104
0
    else if( ( utf16_stream[ 0 ] == 0xff )
105
0
          && ( utf16_stream[ 1 ] == 0xfe ) )
106
0
    {
107
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
108
0
      utf16_stream_index = 2;
109
0
    }
110
0
    if( byte_order == 0 )
111
0
    {
112
0
      byte_order = read_byte_order;
113
0
    }
114
0
  }
115
0
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
116
0
  {
117
    /* Convert the UTF-16 stream bytes into an Unicode character
118
     */
119
0
    if( libuna_unicode_character_copy_from_utf16_stream(
120
0
         &unicode_character,
121
0
         utf16_stream,
122
0
         utf16_stream_size,
123
0
         &utf16_stream_index,
124
0
         byte_order,
125
0
         error ) != 1 )
126
0
    {
127
0
      libcerror_error_set(
128
0
       error,
129
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
130
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
131
0
       "%s: unable to copy Unicode character from UTF-16 stream.",
132
0
       function );
133
134
0
      return( -1 );
135
0
    }
136
0
    switch( unicode_character )
137
0
    {
138
      /* Replace & by &amp; */
139
0
      case (libuna_unicode_character_t) '&':
140
0
        safe_utf8_string_size += 5;
141
0
        break;
142
143
      /* Replace < by &lt; and > by &gt; */
144
0
      case (libuna_unicode_character_t) '<':
145
0
      case (libuna_unicode_character_t) '>':
146
0
        safe_utf8_string_size += 4;
147
0
        break;
148
149
      /* Replace ' by &apos; and " by &quot; */
150
/* TODO disabled for now since Event Viewer does not uses it
151
      case (libuna_unicode_character_t) '\'':
152
      case (libuna_unicode_character_t) '"':
153
        safe_utf8_string_size += 6;
154
        break;
155
*/
156
157
0
      default:
158
        /* Determine how many UTF-8 character bytes are required
159
         */
160
0
        if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
161
0
        {
162
0
          result = libuna_unicode_character_size_to_utf8(
163
0
              unicode_character,
164
0
              &safe_utf8_string_size,
165
0
              error );
166
0
        }
167
0
        else
168
0
        {
169
0
          result = libuna_unicode_character_size_to_utf8_rfc2279(
170
0
              unicode_character,
171
0
              &safe_utf8_string_size,
172
0
              error );
173
0
        }
174
0
        if( result != 1 )
175
0
        {
176
0
          libcerror_error_set(
177
0
           error,
178
0
           LIBCERROR_ERROR_DOMAIN_CONVERSION,
179
0
           LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
180
0
           "%s: unable to unable to determine size of Unicode character in UTF-8.",
181
0
           function );
182
183
0
          return( -1 );
184
0
        }
185
0
        break;
186
0
    }
187
0
    if( unicode_character == 0 )
188
0
    {
189
0
      break;
190
0
    }
191
0
  }
192
  /* Check if the string is terminated with an end-of-string character
193
   */
194
0
  if( unicode_character != 0 )
195
0
  {
196
0
    safe_utf8_string_size++;
197
0
  }
198
0
  *utf8_string_size = safe_utf8_string_size;
199
200
0
  return( 1 );
201
0
}
202
203
/* Copies an UTF-8 XML string from an UTF-16 stream
204
 * Returns 1 if successful or -1 on error
205
 */
206
int libfwevt_utf8_xml_string_with_index_copy_from_utf16_stream(
207
     libuna_utf8_character_t *utf8_string,
208
     size_t utf8_string_size,
209
     size_t *utf8_string_index,
210
     const uint8_t *utf16_stream,
211
     size_t utf16_stream_size,
212
     int byte_order,
213
     libcerror_error_t **error )
214
0
{
215
0
  static char *function                        = "libfwevt_utf8_xml_string_with_index_copy_from_utf16_stream";
216
0
  libuna_unicode_character_t unicode_character = 0;
217
0
  size_t safe_utf8_string_index                = 0;
218
0
  size_t utf16_stream_index                    = 0;
219
0
  int read_byte_order                          = 0;
220
0
  int result                                   = 0;
221
222
0
  if( utf8_string == NULL )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
228
0
     "%s: invalid UTF-8 string.",
229
0
     function );
230
231
0
    return( -1 );
232
0
  }
233
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
238
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
239
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
0
  if( utf8_string_index == NULL )
245
0
  {
246
0
    libcerror_error_set(
247
0
     error,
248
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
249
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
250
0
     "%s: invalid UTF-8 string index.",
251
0
     function );
252
253
0
    return( -1 );
254
0
  }
255
0
  if( utf16_stream == NULL )
256
0
  {
257
0
    libcerror_error_set(
258
0
     error,
259
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
260
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
261
0
     "%s: invalid UTF-16 stream.",
262
0
     function );
263
264
0
    return( -1 );
265
0
  }
266
0
  if( utf16_stream_size > (size_t) SSIZE_MAX )
267
0
  {
268
0
    libcerror_error_set(
269
0
     error,
270
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
272
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
273
0
     function );
274
275
0
    return( -1 );
276
0
  }
277
0
  if( ( utf16_stream_size == 0 )
278
0
   || ( ( utf16_stream_size % 2 ) != 0 ) )
279
0
  {
280
0
    libcerror_error_set(
281
0
     error,
282
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
283
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
284
0
     "%s: missing UTF-16 stream value.",
285
0
     function );
286
287
0
    return( -1 );
288
0
  }
289
  /* Check if UTF-16 stream is in big or little endian
290
   */
291
0
  if( utf16_stream_size >= 2 )
292
0
  {
293
0
    if( ( utf16_stream[ 0 ] == 0xfe )
294
0
     && ( utf16_stream[ 1 ] == 0xff ) )
295
0
    {
296
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
297
0
      utf16_stream_index = 2;
298
0
    }
299
0
    else if( ( utf16_stream[ 0 ] == 0xff )
300
0
          && ( utf16_stream[ 1 ] == 0xfe ) )
301
0
    {
302
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
303
0
      utf16_stream_index = 2;
304
0
    }
305
0
    if( byte_order == 0 )
306
0
    {
307
0
      byte_order = read_byte_order;
308
0
    }
309
0
  }
310
0
  safe_utf8_string_index = *utf8_string_index;
311
312
0
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
313
0
  {
314
    /* Convert the UTF-16 stream bytes into an Unicode character
315
     */
316
0
    if( libuna_unicode_character_copy_from_utf16_stream(
317
0
         &unicode_character,
318
0
         utf16_stream,
319
0
         utf16_stream_size,
320
0
         &utf16_stream_index,
321
0
         byte_order,
322
0
         error ) != 1 )
323
0
    {
324
0
      libcerror_error_set(
325
0
       error,
326
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
327
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
328
0
       "%s: unable to copy Unicode character from UTF-16 stream.",
329
0
       function );
330
331
0
      return( -1 );
332
0
    }
333
0
    switch( unicode_character )
334
0
    {
335
      /* Replace & by &amp; */
336
0
      case (libuna_unicode_character_t) '&':
337
0
        if( ( safe_utf8_string_index + 5 ) > utf8_string_size )
338
0
        {
339
0
          libcerror_error_set(
340
0
           error,
341
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
342
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
343
0
           "%s: UTF-8 string size too small.",
344
0
           function );
345
346
0
          return( -1 );
347
0
        }
348
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '&';
349
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'a';
350
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'm';
351
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'p';
352
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) ';';
353
354
0
        break;
355
356
      /* Replace < by &lt; */
357
0
      case (libuna_unicode_character_t) '<':
358
0
        if( ( safe_utf8_string_index + 4 ) > utf8_string_size )
359
0
        {
360
0
          libcerror_error_set(
361
0
           error,
362
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
363
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
364
0
           "%s: UTF-8 string size too small.",
365
0
           function );
366
367
0
          return( -1 );
368
0
        }
369
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '&';
370
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'l';
371
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 't';
372
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) ';';
373
374
0
        break;
375
376
      /* Replace > by &gt; */
377
0
      case (libuna_unicode_character_t) '>':
378
0
        if( ( safe_utf8_string_index + 4 ) > utf8_string_size )
379
0
        {
380
0
          libcerror_error_set(
381
0
           error,
382
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
383
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
384
0
           "%s: UTF-8 string size too small.",
385
0
           function );
386
387
0
          return( -1 );
388
0
        }
389
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '&';
390
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'g';
391
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 't';
392
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) ';';
393
394
0
        break;
395
396
      /* Replace ' by &apos; */
397
/* TODO disabled for now since Event Viewer does not uses it
398
      case (libuna_unicode_character_t) '\'':
399
        if( ( safe_utf8_string_index + 6 ) > utf8_string_size )
400
        {
401
          libcerror_error_set(
402
           error,
403
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
404
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
405
           "%s: UTF-8 string size too small.",
406
           function );
407
408
          return( -1 );
409
        }
410
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '&';
411
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'a';
412
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'p';
413
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'o';
414
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 's';
415
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) ';';
416
417
        break;
418
*/
419
420
      /* Replace " by &quot; */
421
/* TODO disabled for now since Event Viewer does not uses it
422
      case (libuna_unicode_character_t) '"':
423
        if( ( safe_utf8_string_index + 6 ) > utf8_string_size )
424
        {
425
          libcerror_error_set(
426
           error,
427
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
428
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
429
           "%s: UTF-8 string size too small.",
430
           function );
431
432
          return( -1 );
433
        }
434
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '&';
435
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'q';
436
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'u';
437
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'o';
438
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 't';
439
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) ';';
440
441
        break;
442
*/
443
444
0
      default:
445
        /* Convert the Unicode character into UTF-8 character bytes
446
         */
447
0
        if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
448
0
        {
449
0
          result = libuna_unicode_character_copy_to_utf8(
450
0
              unicode_character,
451
0
              utf8_string,
452
0
              utf8_string_size,
453
0
              &safe_utf8_string_index,
454
0
              error );
455
0
        }
456
0
        else
457
0
        {
458
0
          result = libuna_unicode_character_copy_to_utf8_rfc2279(
459
0
              unicode_character,
460
0
              utf8_string,
461
0
              utf8_string_size,
462
0
              &safe_utf8_string_index,
463
0
              error );
464
0
        }
465
0
        if( result != 1 )
466
0
        {
467
0
          libcerror_error_set(
468
0
           error,
469
0
           LIBCERROR_ERROR_DOMAIN_CONVERSION,
470
0
           LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
471
0
           "%s: unable to copy Unicode character to UTF-8.",
472
0
           function );
473
474
0
          return( -1 );
475
0
        }
476
0
        break;
477
0
    }
478
0
    if( unicode_character == 0 )
479
0
    {
480
0
      break;
481
0
    }
482
0
  }
483
  /* Check if the string is terminated with an end-of-string character
484
   */
485
0
  if( unicode_character != 0 )
486
0
  {
487
0
    if( safe_utf8_string_index >= utf8_string_size )
488
0
    {
489
0
      libcerror_error_set(
490
0
       error,
491
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
492
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
493
0
       "%s: UTF-8 string too small.",
494
0
       function );
495
496
0
      return( -1 );
497
0
    }
498
0
    utf8_string[ safe_utf8_string_index ] = 0;
499
500
0
    safe_utf8_string_index++;
501
0
  }
502
0
  *utf8_string_index = safe_utf8_string_index;
503
504
0
  return( 1 );
505
0
}
506
507
/* Determines the size of an UTF-16 XML string from an UTF-16 stream
508
 * Returns 1 if successful or -1 on error
509
 */
510
int libfwevt_utf16_xml_string_size_from_utf16_stream(
511
     const uint8_t *utf16_stream,
512
     size_t utf16_stream_size,
513
     int byte_order,
514
     size_t *utf16_string_size,
515
     libcerror_error_t **error )
516
0
{
517
0
  static char *function                        = "libfwevt_utf16_xml_string_size_from_utf16_stream";
518
0
  libuna_unicode_character_t unicode_character = 0;
519
0
  size_t safe_utf16_string_size                = 0;
520
0
  size_t utf16_stream_index                    = 0;
521
0
  int read_byte_order                          = 0;
522
0
  int result                                   = 0;
523
524
0
  if( utf16_stream == NULL )
525
0
  {
526
0
    libcerror_error_set(
527
0
     error,
528
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
529
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
530
0
     "%s: invalid UTF-16 stream.",
531
0
     function );
532
533
0
    return( -1 );
534
0
  }
535
0
  if( utf16_stream_size > (size_t) SSIZE_MAX )
536
0
  {
537
0
    libcerror_error_set(
538
0
     error,
539
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
540
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
541
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
542
0
     function );
543
544
0
    return( -1 );
545
0
  }
546
0
  if( ( utf16_stream_size % 2 ) != 0 )
547
0
  {
548
0
    libcerror_error_set(
549
0
     error,
550
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
551
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
552
0
     "%s: missing UTF-16 stream value.",
553
0
     function );
554
555
0
    return( -1 );
556
0
  }
557
0
  if( utf16_string_size == NULL )
558
0
  {
559
0
    libcerror_error_set(
560
0
     error,
561
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
562
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
563
0
     "%s: invalid UTF-16 string size.",
564
0
     function );
565
566
0
    return( -1 );
567
0
  }
568
0
  if( utf16_stream_size == 0 )
569
0
  {
570
0
    return( 1 );
571
0
  }
572
  /* Check if UTF-16 stream is in big or little endian
573
   */
574
0
  if( utf16_stream_size >= 2 )
575
0
  {
576
0
    if( ( utf16_stream[ 0 ] == 0x0ff )
577
0
     && ( utf16_stream[ 1 ] == 0x0fe ) )
578
0
    {
579
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
580
0
      utf16_stream_index = 2;
581
0
    }
582
0
    else if( ( utf16_stream[ 0 ] == 0x0fe )
583
0
          && ( utf16_stream[ 1 ] == 0x0ff ) )
584
0
    {
585
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
586
0
      utf16_stream_index = 2;
587
0
    }
588
0
    if( byte_order == 0 )
589
0
    {
590
0
      byte_order = read_byte_order;
591
0
    }
592
0
  }
593
0
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
594
0
  {
595
    /* Convert the UTF-16 stream bytes into an Unicode character
596
     */
597
0
    if( libuna_unicode_character_copy_from_utf16_stream(
598
0
         &unicode_character,
599
0
         utf16_stream,
600
0
         utf16_stream_size,
601
0
         &utf16_stream_index,
602
0
         byte_order,
603
0
         error ) != 1 )
604
0
    {
605
0
      libcerror_error_set(
606
0
       error,
607
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
608
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
609
0
       "%s: unable to copy Unicode character from UTF-16 stream.",
610
0
       function );
611
612
0
      return( -1 );
613
0
    }
614
0
    switch( unicode_character )
615
0
    {
616
      /* Replace & by &amp; */
617
0
      case (libuna_unicode_character_t) '&':
618
0
        safe_utf16_string_size += 5;
619
0
        break;
620
621
      /* Replace < by &lt; and > by &gt; */
622
0
      case (libuna_unicode_character_t) '<':
623
0
      case (libuna_unicode_character_t) '>':
624
0
        safe_utf16_string_size += 4;
625
0
        break;
626
627
      /* Replace ' by &apos; and " by &quot; */
628
/* TODO disabled for now since Event Viewer does not uses it
629
      case (libuna_unicode_character_t) '\'':
630
      case (libuna_unicode_character_t) '"':
631
        safe_utf16_string_size += 6;
632
        break;
633
*/
634
635
0
      default:
636
        /* Determine how many UTF-16 character bytes are required
637
         */
638
0
        if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
639
0
        {
640
0
          result = libuna_unicode_character_size_to_utf16(
641
0
              unicode_character,
642
0
              &safe_utf16_string_size,
643
0
              error );
644
0
        }
645
0
        else
646
0
        {
647
0
          result = libuna_unicode_character_size_to_ucs2(
648
0
              unicode_character,
649
0
              &safe_utf16_string_size,
650
0
              error );
651
0
        }
652
0
        if( result != 1 )
653
0
        {
654
0
          libcerror_error_set(
655
0
           error,
656
0
           LIBCERROR_ERROR_DOMAIN_CONVERSION,
657
0
           LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
658
0
           "%s: unable to unable to determine size of Unicode character in UTF-16.",
659
0
           function );
660
661
0
          return( -1 );
662
0
        }
663
0
        break;
664
0
    }
665
0
    if( unicode_character == 0 )
666
0
    {
667
0
      break;
668
0
    }
669
0
  }
670
  /* Check if the string is terminated with an end-of-string character
671
   */
672
0
  if( unicode_character != 0 )
673
0
  {
674
0
    safe_utf16_string_size++;
675
0
  }
676
0
  *utf16_string_size = safe_utf16_string_size;
677
678
0
  return( 1 );
679
0
}
680
681
/* Copies an UTF-16 XML string from an UTF-16 stream
682
 * Returns 1 if successful or -1 on error
683
 */
684
int libfwevt_utf16_xml_string_with_index_copy_from_utf16_stream(
685
     libuna_utf16_character_t *utf16_string,
686
     size_t utf16_string_size,
687
     size_t *utf16_string_index,
688
     const uint8_t *utf16_stream,
689
     size_t utf16_stream_size,
690
     int byte_order,
691
     libcerror_error_t **error )
692
0
{
693
0
  static char *function                        = "libfwevt_utf16_xml_string_with_index_copy_from_utf16_stream";
694
0
  libuna_unicode_character_t unicode_character = 0;
695
0
  size_t safe_utf16_string_index               = 0;
696
0
  size_t utf16_stream_index                    = 0;
697
0
  int read_byte_order                          = 0;
698
0
  int result                                   = 0;
699
700
0
  if( utf16_string == NULL )
701
0
  {
702
0
    libcerror_error_set(
703
0
     error,
704
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
705
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
706
0
     "%s: invalid UTF-16 string.",
707
0
     function );
708
709
0
    return( -1 );
710
0
  }
711
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
712
0
  {
713
0
    libcerror_error_set(
714
0
     error,
715
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
716
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
717
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
718
0
     function );
719
720
0
    return( -1 );
721
0
  }
722
0
  if( utf16_string_index == NULL )
723
0
  {
724
0
    libcerror_error_set(
725
0
     error,
726
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
727
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
728
0
     "%s: invalid UTF-16 string index.",
729
0
     function );
730
731
0
    return( -1 );
732
0
  }
733
0
  if( utf16_stream == NULL )
734
0
  {
735
0
    libcerror_error_set(
736
0
     error,
737
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
738
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
739
0
     "%s: invalid UTF-16 stream.",
740
0
     function );
741
742
0
    return( -1 );
743
0
  }
744
0
  if( utf16_stream_size > (size_t) SSIZE_MAX )
745
0
  {
746
0
    libcerror_error_set(
747
0
     error,
748
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
749
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
750
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
751
0
     function );
752
753
0
    return( -1 );
754
0
  }
755
0
  if( ( utf16_stream_size == 0 )
756
0
   || ( ( utf16_stream_size % 2 ) != 0 ) )
757
0
  {
758
0
    libcerror_error_set(
759
0
     error,
760
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
761
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
762
0
     "%s: missing UTF-16 stream value.",
763
0
     function );
764
765
0
    return( -1 );
766
0
  }
767
  /* Check if UTF-16 stream is in big or little endian
768
   */
769
0
  if( utf16_stream_size >= 2 )
770
0
  {
771
0
    if( ( utf16_stream[ 0 ] == 0x0ff )
772
0
     && ( utf16_stream[ 1 ] == 0x0fe ) )
773
0
    {
774
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
775
0
      utf16_stream_index = 2;
776
0
    }
777
0
    else if( ( utf16_stream[ 0 ] == 0x0fe )
778
0
          && ( utf16_stream[ 1 ] == 0x0ff ) )
779
0
    {
780
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
781
0
      utf16_stream_index = 2;
782
0
    }
783
0
    if( byte_order == 0 )
784
0
    {
785
0
      byte_order = read_byte_order;
786
0
    }
787
0
  }
788
0
  safe_utf16_string_index = *utf16_string_index;
789
790
0
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
791
0
  {
792
    /* Convert the UTF-16 stream bytes into an Unicode character
793
     */
794
0
    if( libuna_unicode_character_copy_from_utf16_stream(
795
0
         &unicode_character,
796
0
         utf16_stream,
797
0
         utf16_stream_size,
798
0
         &utf16_stream_index,
799
0
         byte_order,
800
0
         error ) != 1 )
801
0
    {
802
0
      libcerror_error_set(
803
0
       error,
804
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
805
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
806
0
       "%s: unable to copy Unicode character from UTF-16 stream.",
807
0
       function );
808
809
0
      return( -1 );
810
0
    }
811
0
    switch( unicode_character )
812
0
    {
813
      /* Replace & by &amp; */
814
0
      case (libuna_unicode_character_t) '&':
815
0
        if( ( safe_utf16_string_index + 5 ) > utf16_string_size )
816
0
        {
817
0
          libcerror_error_set(
818
0
           error,
819
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
820
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
821
0
           "%s: UTF-16 string size too small.",
822
0
           function );
823
824
0
          return( -1 );
825
0
        }
826
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '&';
827
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'a';
828
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'm';
829
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'p';
830
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) ';';
831
832
0
        break;
833
834
      /* Replace < by &lt; */
835
0
      case (libuna_unicode_character_t) '<':
836
0
        if( ( safe_utf16_string_index + 4 ) > utf16_string_size )
837
0
        {
838
0
          libcerror_error_set(
839
0
           error,
840
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
841
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
842
0
           "%s: UTF-16 string size too small.",
843
0
           function );
844
845
0
          return( -1 );
846
0
        }
847
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '&';
848
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'l';
849
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 't';
850
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) ';';
851
852
0
        break;
853
854
      /* Replace > by &gt; */
855
0
      case (libuna_unicode_character_t) '>':
856
0
        if( ( safe_utf16_string_index + 4 ) > utf16_string_size )
857
0
        {
858
0
          libcerror_error_set(
859
0
           error,
860
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
861
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
862
0
           "%s: UTF-16 string size too small.",
863
0
           function );
864
865
0
          return( -1 );
866
0
        }
867
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '&';
868
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'g';
869
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 't';
870
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) ';';
871
872
0
        break;
873
874
      /* Replace ' by &apos; */
875
/* TODO disabled for now since Event Viewer does not uses it
876
      case (libuna_unicode_character_t) '\'':
877
        if( ( safe_utf16_string_index + 6 ) > utf16_string_size )
878
        {
879
          libcerror_error_set(
880
           error,
881
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
882
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
883
           "%s: UTF-16 string size too small.",
884
           function );
885
886
          return( -1 );
887
        }
888
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '&';
889
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'a';
890
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'p';
891
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'o';
892
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 's';
893
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) ';';
894
895
        break;
896
*/
897
898
      /* Replace " by &quot; */
899
/* TODO disabled for now since Event Viewer does not uses it
900
      case (libuna_unicode_character_t) '"':
901
        if( ( safe_utf16_string_index + 6 ) > utf16_string_size )
902
        {
903
          libcerror_error_set(
904
           error,
905
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
906
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
907
           "%s: UTF-16 string size too small.",
908
           function );
909
910
          return( -1 );
911
        }
912
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '&';
913
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'q';
914
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'u';
915
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'o';
916
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 't';
917
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) ';';
918
919
        break;
920
*/
921
922
0
      default:
923
        /* Convert the Unicode character into UTF-16 character bytes
924
         */
925
0
        if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
926
0
        {
927
0
          result = libuna_unicode_character_copy_to_utf16(
928
0
              unicode_character,
929
0
              utf16_string,
930
0
              utf16_string_size,
931
0
              &safe_utf16_string_index,
932
0
              error );
933
0
        }
934
0
        else
935
0
        {
936
0
          result = libuna_unicode_character_copy_to_ucs2(
937
0
              unicode_character,
938
0
              utf16_string,
939
0
              utf16_string_size,
940
0
              &safe_utf16_string_index,
941
0
              error );
942
0
        }
943
0
        if( result != 1 )
944
0
        {
945
0
          libcerror_error_set(
946
0
           error,
947
0
           LIBCERROR_ERROR_DOMAIN_CONVERSION,
948
0
           LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
949
0
           "%s: unable to copy Unicode character to UTF-16.",
950
0
           function );
951
952
0
          return( -1 );
953
0
        }
954
0
        break;
955
0
    }
956
0
    if( unicode_character == 0 )
957
0
    {
958
0
      break;
959
0
    }
960
0
  }
961
  /* Check if the string is terminated with an end-of-string character
962
   */
963
0
  if( unicode_character != 0 )
964
0
  {
965
0
    if( safe_utf16_string_index >= utf16_string_size )
966
0
    {
967
0
      libcerror_error_set(
968
0
       error,
969
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
970
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
971
0
       "%s: UTF-16 string too small.",
972
0
       function );
973
974
0
      return( -1 );
975
0
    }
976
0
    utf16_string[ safe_utf16_string_index ] = 0;
977
978
0
    safe_utf16_string_index++;
979
0
  }
980
0
  *utf16_string_index = safe_utf16_string_index;
981
982
0
  return( 1 );
983
0
}
984