1 /*
2 * Strings array functions
3 *
4 * Copyright (C) 2011-2021, 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 "libevt_libcerror.h"
27 #include "libevt_libcnotify.h"
28 #include "libevt_libuna.h"
29 #include "libevt_strings_array.h"
30
31 /* Creates a strings array
32 * Make sure the value strings_array is referencing, is set to NULL
33 * Returns 1 if successful or -1 on error
34 */
libevt_strings_array_initialize(libevt_strings_array_t ** strings_array,libcerror_error_t ** error)35 int libevt_strings_array_initialize(
36 libevt_strings_array_t **strings_array,
37 libcerror_error_t **error )
38 {
39 static char *function = "libevt_strings_array_initialize";
40
41 if( strings_array == NULL )
42 {
43 libcerror_error_set(
44 error,
45 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
46 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
47 "%s: invalid strings array.",
48 function );
49
50 return( -1 );
51 }
52 if( *strings_array != NULL )
53 {
54 libcerror_error_set(
55 error,
56 LIBCERROR_ERROR_DOMAIN_RUNTIME,
57 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
58 "%s: invalid strings array value already set.",
59 function );
60
61 return( -1 );
62 }
63 *strings_array = memory_allocate_structure(
64 libevt_strings_array_t );
65
66 if( *strings_array == NULL )
67 {
68 libcerror_error_set(
69 error,
70 LIBCERROR_ERROR_DOMAIN_MEMORY,
71 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
72 "%s: unable to create strings array.",
73 function );
74
75 goto on_error;
76 }
77 if( memory_set(
78 *strings_array,
79 0,
80 sizeof( libevt_strings_array_t ) ) == NULL )
81 {
82 libcerror_error_set(
83 error,
84 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 LIBCERROR_MEMORY_ERROR_SET_FAILED,
86 "%s: unable to clear strings array.",
87 function );
88
89 goto on_error;
90 }
91 return( 1 );
92
93 on_error:
94 if( *strings_array != NULL )
95 {
96 memory_free(
97 *strings_array );
98
99 *strings_array = NULL;
100 }
101 return( -1 );
102 }
103
104 /* Frees a strings array
105 * Returns 1 if successful or -1 on error
106 */
libevt_strings_array_free(libevt_strings_array_t ** strings_array,libcerror_error_t ** error)107 int libevt_strings_array_free(
108 libevt_strings_array_t **strings_array,
109 libcerror_error_t **error )
110 {
111 static char *function = "libevt_strings_array_free";
112
113 if( strings_array == NULL )
114 {
115 libcerror_error_set(
116 error,
117 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
118 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
119 "%s: invalid strings array.",
120 function );
121
122 return( -1 );
123 }
124 if( *strings_array != NULL )
125 {
126 if( ( *strings_array )->string_sizes != NULL )
127 {
128 memory_free(
129 ( *strings_array )->string_sizes );
130 }
131 if( ( *strings_array )->strings != NULL )
132 {
133 memory_free(
134 ( *strings_array )->strings );
135 }
136 if( ( *strings_array )->strings_data != NULL )
137 {
138 memory_free(
139 ( *strings_array )->strings_data );
140 }
141 memory_free(
142 *strings_array );
143
144 *strings_array = NULL;
145 }
146 return( 1 );
147 }
148
149 /* Reads the strings array data
150 * Returns 1 if successful or -1 on error
151 */
libevt_strings_array_read_data(libevt_strings_array_t * strings_array,const uint8_t * data,size_t data_size,libcerror_error_t ** error)152 int libevt_strings_array_read_data(
153 libevt_strings_array_t *strings_array,
154 const uint8_t *data,
155 size_t data_size,
156 libcerror_error_t **error )
157 {
158 static char *function = "libevt_strings_array_read_data";
159 size_t data_offset = 0;
160 size_t string_offset = 0;
161 int number_of_strings = 0;
162 int string_index = 0;
163
164 if( strings_array == NULL )
165 {
166 libcerror_error_set(
167 error,
168 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170 "%s: invalid strings array.",
171 function );
172
173 return( -1 );
174 }
175 if( strings_array->strings_data != NULL )
176 {
177 libcerror_error_set(
178 error,
179 LIBCERROR_ERROR_DOMAIN_RUNTIME,
180 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
181 "%s: invalid strings array - strings data value already set.",
182 function );
183
184 return( -1 );
185 }
186 if( data == NULL )
187 {
188 libcerror_error_set(
189 error,
190 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
191 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
192 "%s: invalid data.",
193 function );
194
195 return( -1 );
196 }
197 if( ( data_size < 2 )
198 || ( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
199 {
200 libcerror_error_set(
201 error,
202 LIBCERROR_ERROR_DOMAIN_RUNTIME,
203 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
204 "%s: invalid data size value out of bounds.",
205 function );
206
207 return( -1 );
208 }
209 if( ( data_size % 2 ) != 0 )
210 {
211 libcerror_error_set(
212 error,
213 LIBCERROR_ERROR_DOMAIN_RUNTIME,
214 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
215 "%s: invalid data size - value must be a multitude of 2.",
216 function );
217
218 return( -1 );
219 }
220 #if defined( HAVE_DEBUG_OUTPUT )
221 if( libcnotify_verbose != 0 )
222 {
223 libcnotify_printf(
224 "%s: strings array data:\n",
225 function );
226 libcnotify_print_data(
227 data,
228 data_size,
229 0 );
230 }
231 #endif
232 for( data_offset = 0;
233 data_offset < data_size;
234 data_offset += 2 )
235 {
236 if( ( data[ data_offset ] == 0 )
237 && ( data[ data_offset + 1 ] == 0 ) )
238 {
239 number_of_strings++;
240 }
241 }
242 #if defined( HAVE_DEBUG_OUTPUT )
243 if( libcnotify_verbose != 0 )
244 {
245 libcnotify_printf(
246 "%s: number of strings\t\t\t: %d\n",
247 function,
248 number_of_strings );
249
250 libcnotify_printf(
251 "\n" );
252 }
253 #endif
254 strings_array->strings_data = (uint8_t *) memory_allocate(
255 sizeof( uint8_t ) * data_size );
256
257 if( strings_array->strings_data == NULL )
258 {
259 libcerror_error_set(
260 error,
261 LIBCERROR_ERROR_DOMAIN_MEMORY,
262 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
263 "%s: unable to create strings data.",
264 function );
265
266 goto on_error;
267 }
268 if( memory_copy(
269 strings_array->strings_data,
270 data,
271 sizeof( uint8_t ) * data_size ) == NULL )
272 {
273 libcerror_error_set(
274 error,
275 LIBCERROR_ERROR_DOMAIN_MEMORY,
276 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
277 "%s: unable to copy strings data.",
278 function );
279
280 goto on_error;
281 }
282 strings_array->strings_data_size = data_size;
283
284 strings_array->strings = (uint8_t **) memory_allocate(
285 sizeof( uint8_t* ) * number_of_strings );
286
287 if( strings_array->strings == NULL )
288 {
289 libcerror_error_set(
290 error,
291 LIBCERROR_ERROR_DOMAIN_MEMORY,
292 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
293 "%s: unable to create strings.",
294 function );
295
296 goto on_error;
297 }
298 if( memory_set(
299 strings_array->strings,
300 0,
301 sizeof( uint8_t* ) * number_of_strings ) == NULL )
302 {
303 libcerror_error_set(
304 error,
305 LIBCERROR_ERROR_DOMAIN_MEMORY,
306 LIBCERROR_MEMORY_ERROR_SET_FAILED,
307 "%s: unable to clear strings.",
308 function );
309
310 goto on_error;
311 }
312 strings_array->string_sizes = (size_t *) memory_allocate(
313 sizeof( size_t ) * number_of_strings );
314
315 if( strings_array->string_sizes == NULL )
316 {
317 libcerror_error_set(
318 error,
319 LIBCERROR_ERROR_DOMAIN_MEMORY,
320 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
321 "%s: unable to create string sizes.",
322 function );
323
324 goto on_error;
325 }
326 if( memory_set(
327 strings_array->string_sizes,
328 0,
329 sizeof( uint8_t* ) * number_of_strings ) == NULL )
330 {
331 libcerror_error_set(
332 error,
333 LIBCERROR_ERROR_DOMAIN_MEMORY,
334 LIBCERROR_MEMORY_ERROR_SET_FAILED,
335 "%s: unable to clear string sizes.",
336 function );
337
338 goto on_error;
339 }
340 for( data_offset = 0;
341 data_offset < strings_array->strings_data_size;
342 data_offset += 2 )
343 {
344 if( ( strings_array->strings_data[ data_offset ] == 0 )
345 && ( strings_array->strings_data[ data_offset + 1 ] == 0 ) )
346 {
347 strings_array->strings[ string_index ] = &( strings_array->strings_data[ string_offset ] );
348 strings_array->string_sizes[ string_index ] = ( data_offset + 2 ) - string_offset;
349
350 #if defined( HAVE_DEBUG_OUTPUT )
351 if( libcnotify_verbose != 0 )
352 {
353 libcnotify_printf(
354 "%s: string: %d data:\n",
355 function,
356 string_index );
357 libcnotify_print_data(
358 strings_array->strings[ string_index ],
359 strings_array->string_sizes[ string_index ],
360 0 );
361 }
362 #endif
363 string_offset = data_offset + 2;
364
365 string_index++;
366 }
367 }
368 strings_array->number_of_strings = number_of_strings;
369
370 return( 1 );
371
372 on_error:
373 if( strings_array->string_sizes != NULL )
374 {
375 memory_free(
376 strings_array->string_sizes );
377
378 strings_array->string_sizes = NULL;
379 }
380 if( strings_array->strings != NULL )
381 {
382 memory_free(
383 strings_array->strings );
384
385 strings_array->strings = NULL;
386 }
387 if( strings_array->strings_data != NULL )
388 {
389 memory_free(
390 strings_array->strings_data );
391
392 strings_array->strings_data = NULL;
393 }
394 strings_array->strings_data_size = 0;
395
396 return( -1 );
397 }
398
399 /* Retrieves the number of strings
400 * Returns 1 if successful or -1 on error
401 */
libevt_strings_array_get_number_of_strings(libevt_strings_array_t * strings_array,int * number_of_strings,libcerror_error_t ** error)402 int libevt_strings_array_get_number_of_strings(
403 libevt_strings_array_t *strings_array,
404 int *number_of_strings,
405 libcerror_error_t **error )
406 {
407 static char *function = "libevt_strings_array_get_number_of_strings";
408
409 if( strings_array == NULL )
410 {
411 libcerror_error_set(
412 error,
413 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
415 "%s: invalid strings array.",
416 function );
417
418 return( -1 );
419 }
420 if( number_of_strings == NULL )
421 {
422 libcerror_error_set(
423 error,
424 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
425 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
426 "%s: invalid number of strings.",
427 function );
428
429 return( -1 );
430 }
431 *number_of_strings = strings_array->number_of_strings;
432
433 return( 1 );
434 }
435
436 /* Retrieves the size of a specific UTF-8 encoded string
437 * The returned size includes the end of string character
438 * Returns 1 if successful or -1 on error
439 */
libevt_strings_array_get_utf8_string_size(libevt_strings_array_t * strings_array,int string_index,size_t * utf8_string_size,libcerror_error_t ** error)440 int libevt_strings_array_get_utf8_string_size(
441 libevt_strings_array_t *strings_array,
442 int string_index,
443 size_t *utf8_string_size,
444 libcerror_error_t **error )
445 {
446 static char *function = "libevt_strings_array_get_utf8_string_size";
447
448 if( strings_array == NULL )
449 {
450 libcerror_error_set(
451 error,
452 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
453 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
454 "%s: invalid record values.",
455 function );
456
457 return( -1 );
458 }
459 if( strings_array->strings == NULL )
460 {
461 libcerror_error_set(
462 error,
463 LIBCERROR_ERROR_DOMAIN_RUNTIME,
464 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
465 "%s: invalid string index value out of bounds.",
466 function );
467
468 return( -1 );
469 }
470 if( ( string_index < 0 )
471 || ( string_index >= strings_array->number_of_strings ) )
472 {
473 libcerror_error_set(
474 error,
475 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
476 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
477 "%s: invalid strings index value out of bounds.",
478 function );
479
480 return( -1 );
481 }
482 if( libuna_utf8_string_size_from_utf16_stream(
483 strings_array->strings[ string_index ],
484 strings_array->string_sizes[ string_index ],
485 LIBUNA_ENDIAN_LITTLE,
486 utf8_string_size,
487 error ) != 1 )
488 {
489 libcerror_error_set(
490 error,
491 LIBCERROR_ERROR_DOMAIN_RUNTIME,
492 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
493 "%s: unable to determine size of UTF-8 string: %d.",
494 function,
495 string_index );
496
497 return( -1 );
498 }
499 return( 1 );
500 }
501
502 /* Retrieves a specific UTF-8 encoded string
503 * The size should include the end of string character
504 * Returns 1 if successful or -1 on error
505 */
libevt_strings_array_get_utf8_string(libevt_strings_array_t * strings_array,int string_index,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)506 int libevt_strings_array_get_utf8_string(
507 libevt_strings_array_t *strings_array,
508 int string_index,
509 uint8_t *utf8_string,
510 size_t utf8_string_size,
511 libcerror_error_t **error )
512 {
513 static char *function = "libevt_values_record_get_utf8_string";
514
515 if( strings_array == NULL )
516 {
517 libcerror_error_set(
518 error,
519 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
521 "%s: invalid record values.",
522 function );
523
524 return( -1 );
525 }
526 if( strings_array->strings == NULL )
527 {
528 libcerror_error_set(
529 error,
530 LIBCERROR_ERROR_DOMAIN_RUNTIME,
531 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
532 "%s: invalid string index value out of bounds.",
533 function );
534
535 return( -1 );
536 }
537 if( ( string_index < 0 )
538 || ( string_index >= strings_array->number_of_strings ) )
539 {
540 libcerror_error_set(
541 error,
542 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
543 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
544 "%s: invalid strings index value out of bounds.",
545 function );
546
547 return( -1 );
548 }
549 if( libuna_utf8_string_copy_from_utf16_stream(
550 (libuna_utf8_character_t *) utf8_string,
551 utf8_string_size,
552 strings_array->strings[ string_index ],
553 strings_array->string_sizes[ string_index ],
554 LIBUNA_ENDIAN_LITTLE,
555 error ) != 1 )
556 {
557 libcerror_error_set(
558 error,
559 LIBCERROR_ERROR_DOMAIN_RUNTIME,
560 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
561 "%s: unable to set UTF-8 string: %d.",
562 function,
563 string_index );
564
565 return( -1 );
566 }
567 return( 1 );
568 }
569
570 /* Retrieves the size of a specific UTF-16 encoded string
571 * The returned size includes the end of string character
572 * Returns 1 if successful or -1 on error
573 */
libevt_strings_array_get_utf16_string_size(libevt_strings_array_t * strings_array,int string_index,size_t * utf16_string_size,libcerror_error_t ** error)574 int libevt_strings_array_get_utf16_string_size(
575 libevt_strings_array_t *strings_array,
576 int string_index,
577 size_t *utf16_string_size,
578 libcerror_error_t **error )
579 {
580 static char *function = "libevt_strings_array_get_utf16_string_size";
581
582 if( strings_array == NULL )
583 {
584 libcerror_error_set(
585 error,
586 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
587 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
588 "%s: invalid record values.",
589 function );
590
591 return( -1 );
592 }
593 if( strings_array->strings == NULL )
594 {
595 libcerror_error_set(
596 error,
597 LIBCERROR_ERROR_DOMAIN_RUNTIME,
598 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
599 "%s: invalid string index value out of bounds.",
600 function );
601
602 return( -1 );
603 }
604 if( ( string_index < 0 )
605 || ( string_index >= strings_array->number_of_strings ) )
606 {
607 libcerror_error_set(
608 error,
609 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
610 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
611 "%s: invalid strings index value out of bounds.",
612 function );
613
614 return( -1 );
615 }
616 if( libuna_utf16_string_size_from_utf16_stream(
617 strings_array->strings[ string_index ],
618 strings_array->string_sizes[ string_index ],
619 LIBUNA_ENDIAN_LITTLE,
620 utf16_string_size,
621 error ) != 1 )
622 {
623 libcerror_error_set(
624 error,
625 LIBCERROR_ERROR_DOMAIN_RUNTIME,
626 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
627 "%s: unable to determine size of UTF-16 string: %d.",
628 function,
629 string_index );
630
631 return( -1 );
632 }
633 return( 1 );
634 }
635
636 /* Retrieves a specific UTF-16 encoded string
637 * The size should include the end of string character
638 * Returns 1 if successful or -1 on error
639 */
libevt_strings_array_get_utf16_string(libevt_strings_array_t * strings_array,int string_index,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)640 int libevt_strings_array_get_utf16_string(
641 libevt_strings_array_t *strings_array,
642 int string_index,
643 uint16_t *utf16_string,
644 size_t utf16_string_size,
645 libcerror_error_t **error )
646 {
647 static char *function = "libevt_values_record_get_utf16_string";
648
649 if( strings_array == NULL )
650 {
651 libcerror_error_set(
652 error,
653 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
654 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
655 "%s: invalid record values.",
656 function );
657
658 return( -1 );
659 }
660 if( strings_array->strings == NULL )
661 {
662 libcerror_error_set(
663 error,
664 LIBCERROR_ERROR_DOMAIN_RUNTIME,
665 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
666 "%s: invalid string index value out of bounds.",
667 function );
668
669 return( -1 );
670 }
671 if( ( string_index < 0 )
672 || ( string_index >= strings_array->number_of_strings ) )
673 {
674 libcerror_error_set(
675 error,
676 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
677 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
678 "%s: invalid strings index value out of bounds.",
679 function );
680
681 return( -1 );
682 }
683 if( libuna_utf16_string_copy_from_utf16_stream(
684 (libuna_utf16_character_t *) utf16_string,
685 utf16_string_size,
686 strings_array->strings[ string_index ],
687 strings_array->string_sizes[ string_index ],
688 LIBUNA_ENDIAN_LITTLE,
689 error ) != 1 )
690 {
691 libcerror_error_set(
692 error,
693 LIBCERROR_ERROR_DOMAIN_RUNTIME,
694 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
695 "%s: unable to set UTF-16 string: %d.",
696 function,
697 string_index );
698
699 return( -1 );
700 }
701 return( 1 );
702 }
703
704