1 /*
2  * Functions for testing
3  *
4  * Copyright (C) 2020-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 <file_stream.h>
24 #include <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28 
29 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
30 #include <stdlib.h>
31 #endif
32 
33 #include "fsxfs_test_libbfio.h"
34 #include "fsxfs_test_libcerror.h"
35 #include "fsxfs_test_libclocale.h"
36 #include "fsxfs_test_libuna.h"
37 
38 /* Retrieves source as a narrow string
39  * Returns 1 if successful or -1 on error
40  */
fsxfs_test_get_narrow_source(const system_character_t * source,char * narrow_string,size_t narrow_string_size,libcerror_error_t ** error)41 int fsxfs_test_get_narrow_source(
42      const system_character_t *source,
43      char *narrow_string,
44      size_t narrow_string_size,
45      libcerror_error_t **error )
46 {
47 	static char *function     = "fsxfs_test_get_narrow_source";
48 	size_t narrow_source_size = 0;
49 	size_t source_length      = 0;
50 
51 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
52 	int result                = 0;
53 #endif
54 
55 	if( source == NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 		 "%s: invalid source.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	if( narrow_string == NULL )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72 		 "%s: invalid narrow string.",
73 		 function );
74 
75 		return( -1 );
76 	}
77 	if( narrow_string_size > (size_t) SSIZE_MAX )
78 	{
79 		libcerror_error_set(
80 		 error,
81 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
83 		 "%s: invalid narrow string size value exceeds maximum.",
84 		 function );
85 
86 		return( -1 );
87 	}
88 	source_length = system_string_length(
89 	                 source );
90 
91 	if( source_length > (size_t) ( SSIZE_MAX - 1 ) )
92 	{
93 		libcerror_error_set(
94 		 error,
95 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
96 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
97 		 "%s: invalid source length value out of bounds.",
98 		 function );
99 
100 		return( -1 );
101 	}
102 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
103 	if( libclocale_codepage == 0 )
104 	{
105 #if SIZEOF_WCHAR_T == 4
106 		result = libuna_utf8_string_size_from_utf32(
107 		          (libuna_utf32_character_t *) source,
108 		          source_length + 1,
109 		          &narrow_source_size,
110 		          error );
111 #elif SIZEOF_WCHAR_T == 2
112 		result = libuna_utf8_string_size_from_utf16(
113 		          (libuna_utf16_character_t *) source,
114 		          source_length + 1,
115 		          &narrow_source_size,
116 		          error );
117 #endif
118 	}
119 	else
120 	{
121 #if SIZEOF_WCHAR_T == 4
122 		result = libuna_byte_stream_size_from_utf32(
123 		          (libuna_utf32_character_t *) source,
124 		          source_length + 1,
125 		          libclocale_codepage,
126 		          &narrow_source_size,
127 		          error );
128 #elif SIZEOF_WCHAR_T == 2
129 		result = libuna_byte_stream_size_from_utf16(
130 		          (libuna_utf16_character_t *) source,
131 		          source_length + 1,
132 		          libclocale_codepage,
133 		          &narrow_source_size,
134 		          error );
135 #endif
136 	}
137 	if( result != 1 )
138 	{
139 		libcerror_error_set(
140 		 error,
141 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
142 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
143 		 "%s: unable to determine narrow string size.",
144 		 function );
145 
146 		return( -1 );
147 	}
148 #else
149 	narrow_source_size = source_length + 1;
150 
151 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
152 
153 	if( narrow_string_size < narrow_source_size )
154 	{
155 		libcerror_error_set(
156 		 error,
157 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
158 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
159 		 "%s: narrow string too small.",
160 		 function );
161 
162 		return( -1 );
163 	}
164 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
165 	if( libclocale_codepage == 0 )
166 	{
167 #if SIZEOF_WCHAR_T == 4
168 		result = libuna_utf8_string_copy_from_utf32(
169 		          (libuna_utf8_character_t *) narrow_string,
170 		          narrow_string_size,
171 		          (libuna_utf32_character_t *) source,
172 		          source_length + 1,
173 		          error );
174 #elif SIZEOF_WCHAR_T == 2
175 		result = libuna_utf8_string_copy_from_utf16(
176 		          (libuna_utf8_character_t *) narrow_string,
177 		          narrow_string_size,
178 		          (libuna_utf16_character_t *) source,
179 		          source_length + 1,
180 		          error );
181 #endif
182 	}
183 	else
184 	{
185 #if SIZEOF_WCHAR_T == 4
186 		result = libuna_byte_stream_copy_from_utf32(
187 		          (uint8_t *) narrow_string,
188 		          narrow_string_size,
189 		          libclocale_codepage,
190 		          (libuna_utf32_character_t *) source,
191 		          source_length + 1,
192 		          error );
193 #elif SIZEOF_WCHAR_T == 2
194 		result = libuna_byte_stream_copy_from_utf16(
195 		          (uint8_t *) narrow_string,
196 		          narrow_string_size,
197 		          libclocale_codepage,
198 		          (libuna_utf16_character_t *) source,
199 		          source_length + 1,
200 		          error );
201 #endif
202 	}
203 	if( result != 1 )
204 	{
205 		libcerror_error_set(
206 		 error,
207 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
208 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
209 		 "%s: unable to set narrow string.",
210 		 function );
211 
212 		return( -1 );
213 	}
214 #else
215 	if( system_string_copy(
216 	     narrow_string,
217 	     source,
218 	     source_length ) == NULL )
219 	{
220 		libcerror_error_set(
221 		 error,
222 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
223 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
224 		 "%s: unable to set narrow string.",
225 		 function );
226 
227 		return( -1 );
228 	}
229 	narrow_string[ source_length ] = 0;
230 
231 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
232 
233 	return( 1 );
234 }
235 
236 #if defined( HAVE_WIDE_CHARACTER_TYPE )
237 
238 /* Retrieves source as a wide string
239  * Returns 1 if successful or -1 on error
240  */
fsxfs_test_get_wide_source(const system_character_t * source,wchar_t * wide_string,size_t wide_string_size,libcerror_error_t ** error)241 int fsxfs_test_get_wide_source(
242      const system_character_t *source,
243      wchar_t *wide_string,
244      size_t wide_string_size,
245      libcerror_error_t **error )
246 {
247 	static char *function   = "fsxfs_test_get_wide_source";
248 	size_t wide_source_size = 0;
249 	size_t source_length    = 0;
250 
251 #if !defined( HAVE_WIDE_SYSTEM_CHARACTER )
252 	int result              = 0;
253 #endif
254 
255 	if( source == NULL )
256 	{
257 		libcerror_error_set(
258 		 error,
259 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
260 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
261 		 "%s: invalid source.",
262 		 function );
263 
264 		return( -1 );
265 	}
266 	if( wide_string == NULL )
267 	{
268 		libcerror_error_set(
269 		 error,
270 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272 		 "%s: invalid wide string.",
273 		 function );
274 
275 		return( -1 );
276 	}
277 	if( wide_string_size > (size_t) SSIZE_MAX )
278 	{
279 		libcerror_error_set(
280 		 error,
281 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
282 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
283 		 "%s: invalid wide string size value exceeds maximum.",
284 		 function );
285 
286 		return( -1 );
287 	}
288 	source_length = system_string_length(
289 	                 source );
290 
291 	if( source_length > (size_t) ( SSIZE_MAX - 1 ) )
292 	{
293 		libcerror_error_set(
294 		 error,
295 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
296 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
297 		 "%s: invalid source length value out of bounds.",
298 		 function );
299 
300 		return( -1 );
301 	}
302 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
303 	wide_source_size = source_length + 1;
304 #else
305 	if( libclocale_codepage == 0 )
306 	{
307 #if SIZEOF_WCHAR_T == 4
308 		result = libuna_utf32_string_size_from_utf8(
309 		          (libuna_utf8_character_t *) source,
310 		          source_length + 1,
311 		          &wide_source_size,
312 		          error );
313 #elif SIZEOF_WCHAR_T == 2
314 		result = libuna_utf16_string_size_from_utf8(
315 		          (libuna_utf8_character_t *) source,
316 		          source_length + 1,
317 		          &wide_source_size,
318 		          error );
319 #endif
320 	}
321 	else
322 	{
323 #if SIZEOF_WCHAR_T == 4
324 		result = libuna_utf32_string_size_from_byte_stream(
325 		          (uint8_t *) source,
326 		          source_length + 1,
327 		          libclocale_codepage,
328 		          &wide_source_size,
329 		          error );
330 #elif SIZEOF_WCHAR_T == 2
331 		result = libuna_utf16_string_size_from_byte_stream(
332 		          (uint8_t *) source,
333 		          source_length + 1,
334 		          libclocale_codepage,
335 		          &wide_source_size,
336 		          error );
337 #endif
338 	}
339 	if( result != 1 )
340 	{
341 		libcerror_error_set(
342 		 error,
343 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
344 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
345 		 "%s: unable to determine wide string size.",
346 		 function );
347 
348 		return( -1 );
349 	}
350 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
351 
352 	if( wide_string_size < wide_source_size )
353 	{
354 		libcerror_error_set(
355 		 error,
356 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
357 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
358 		 "%s: wide string too small.",
359 		 function );
360 
361 		return( -1 );
362 	}
363 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
364 	if( system_string_copy(
365 	     wide_string,
366 	     source,
367 	     source_length ) == NULL )
368 	{
369 		libcerror_error_set(
370 		 error,
371 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
372 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
373 		 "%s: unable to set wide string.",
374 		 function );
375 
376 		return( -1 );
377 	}
378 	wide_string[ source_length ] = 0;
379 #else
380 	if( libclocale_codepage == 0 )
381 	{
382 #if SIZEOF_WCHAR_T == 4
383 		result = libuna_utf32_string_copy_from_utf8(
384 		          (libuna_utf32_character_t *) wide_string,
385 		          wide_string_size,
386 		          (uint8_t *) source,
387 		          source_length + 1,
388 		          error );
389 #elif SIZEOF_WCHAR_T == 2
390 		result = libuna_utf16_string_copy_from_utf8(
391 		          (libuna_utf16_character_t *) wide_string,
392 		          wide_string_size,
393 		          (uint8_t *) source,
394 		          source_length + 1,
395 		          error );
396 #endif
397 	}
398 	else
399 	{
400 #if SIZEOF_WCHAR_T == 4
401 		result = libuna_utf32_string_copy_from_byte_stream(
402 		          (libuna_utf32_character_t *) wide_string,
403 		          wide_string_size,
404 		          (uint8_t *) source,
405 		          source_length + 1,
406 		          libclocale_codepage,
407 		          error );
408 #elif SIZEOF_WCHAR_T == 2
409 		result = libuna_utf16_string_copy_from_byte_stream(
410 		          (libuna_utf16_character_t *) wide_string,
411 		          wide_string_size,
412 		          (uint8_t *) source,
413 		          source_length + 1,
414 		          libclocale_codepage,
415 		          error );
416 #endif
417 	}
418 	if( result != 1 )
419 	{
420 		libcerror_error_set(
421 		 error,
422 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
423 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
424 		 "%s: unable to set wide string.",
425 		 function );
426 
427 		return( -1 );
428 	}
429 
430 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
431 
432 	return( 1 );
433 }
434 
435 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
436 
437 /* Copies a string of a decimal value to a 64-bit value
438  * Returns 1 if successful or -1 on error
439  */
fsxfs_test_system_string_copy_from_64_bit_in_decimal(const system_character_t * string,size_t string_size,uint64_t * value_64bit,libcerror_error_t ** error)440 int fsxfs_test_system_string_copy_from_64_bit_in_decimal(
441      const system_character_t *string,
442      size_t string_size,
443      uint64_t *value_64bit,
444      libcerror_error_t **error )
445 {
446 	static char *function              = "fsxfs_test_system_string_copy_from_64_bit_in_decimal";
447 	size_t string_index                = 0;
448 	system_character_t character_value = 0;
449 	uint8_t maximum_string_index       = 20;
450 	int8_t sign                        = 1;
451 
452 	if( string == NULL )
453 	{
454 		libcerror_error_set(
455 		 error,
456 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458 		 "%s: invalid string.",
459 		 function );
460 
461 		return( -1 );
462 	}
463 	if( string_size > (size_t) SSIZE_MAX )
464 	{
465 		libcerror_error_set(
466 		 error,
467 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
469 		 "%s: invalid string size value exceeds maximum.",
470 		 function );
471 
472 		return( -1 );
473 	}
474 	if( value_64bit == NULL )
475 	{
476 		libcerror_error_set(
477 		 error,
478 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
479 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
480 		 "%s: invalid value 64-bit.",
481 		 function );
482 
483 		return( -1 );
484 	}
485 	*value_64bit = 0;
486 
487 	if( string[ string_index ] == (system_character_t) '-' )
488 	{
489 		string_index++;
490 		maximum_string_index++;
491 
492 		sign = -1;
493 	}
494 	else if( string[ string_index ] == (system_character_t) '+' )
495 	{
496 		string_index++;
497 		maximum_string_index++;
498 	}
499 	while( string_index < string_size )
500 	{
501 		if( string[ string_index ] == 0 )
502 		{
503 			break;
504 		}
505 		if( string_index > (size_t) maximum_string_index )
506 		{
507 			libcerror_error_set(
508 			 error,
509 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510 			 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE,
511 			 "%s: string too large.",
512 			 function );
513 
514 			return( -1 );
515 		}
516 		*value_64bit *= 10;
517 
518 		if( ( string[ string_index ] >= (system_character_t) '0' )
519 		 && ( string[ string_index ] <= (system_character_t) '9' ) )
520 		{
521 			character_value = (system_character_t) ( string[ string_index ] - (system_character_t) '0' );
522 		}
523 		else
524 		{
525 			libcerror_error_set(
526 			 error,
527 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
528 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
529 			 "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.",
530 			 function,
531 			 string[ string_index ],
532 			 string_index );
533 
534 			return( -1 );
535 		}
536 		*value_64bit += character_value;
537 
538 		string_index++;
539 	}
540 	if( sign == -1 )
541 	{
542 		*value_64bit *= (uint64_t) -1;
543 	}
544 	return( 1 );
545 }
546 
547 /* Creates a file IO handle for test data
548  * Returns 1 if successful or -1 on error
549  */
fsxfs_test_open_file_io_handle(libbfio_handle_t ** file_io_handle,uint8_t * data,size_t data_size,libcerror_error_t ** error)550 int fsxfs_test_open_file_io_handle(
551      libbfio_handle_t **file_io_handle,
552      uint8_t *data,
553      size_t data_size,
554      libcerror_error_t **error )
555 {
556 	static char *function = "fsxfs_test_open_file_io_handle";
557 
558 	if( file_io_handle == NULL )
559 	{
560 		libcerror_error_set(
561 		 error,
562 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
563 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
564 		 "%s: invalid file IO handle.",
565 		 function );
566 
567 		return( -1 );
568 	}
569 	if( libbfio_memory_range_initialize(
570 	     file_io_handle,
571 	     error ) != 1 )
572 	{
573 		libcerror_error_set(
574 		 error,
575 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
576 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
577 		 "%s: unable to create file IO handle.",
578 		 function );
579 
580 		goto on_error;
581 	}
582 	if( libbfio_memory_range_set(
583 	     *file_io_handle,
584 	     data,
585 	     data_size,
586 	     error ) != 1 )
587 	{
588 		libcerror_error_set(
589 		 error,
590 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
591 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
592 		 "%s: unable to set memory range of file IO handle.",
593 		 function );
594 
595 		goto on_error;
596 	}
597 	if( libbfio_handle_open(
598 	     *file_io_handle,
599 	     LIBBFIO_OPEN_READ,
600 	     error ) != 1 )
601 	{
602 		libcerror_error_set(
603 		 error,
604 		 LIBCERROR_ERROR_DOMAIN_IO,
605 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
606 		 "%s: unable to open file IO handle.",
607 		 function );
608 
609 		goto on_error;
610 	}
611 	return( 1 );
612 
613 on_error:
614 	if( *file_io_handle != NULL )
615 	{
616 		libbfio_handle_free(
617 		 file_io_handle,
618 		 NULL );
619 	}
620 	return( -1 );
621 }
622 
623 /* Closes a file IO handle for test data
624  * Returns 0 if successful or -1 on error
625  */
fsxfs_test_close_file_io_handle(libbfio_handle_t ** file_io_handle,libcerror_error_t ** error)626 int fsxfs_test_close_file_io_handle(
627      libbfio_handle_t **file_io_handle,
628      libcerror_error_t **error )
629 {
630 	static char *function = "fsxfs_test_close_file_io_handle";
631 	int result            = 0;
632 
633 	if( file_io_handle == NULL )
634 	{
635 		libcerror_error_set(
636 		 error,
637 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
638 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
639 		 "%s: invalid file IO handle.",
640 		 function );
641 
642 		return( -1 );
643 	}
644 	if( libbfio_handle_close(
645 	     *file_io_handle,
646 	     error ) != 0 )
647 	{
648 		libcerror_error_set(
649 		 error,
650 		 LIBCERROR_ERROR_DOMAIN_IO,
651 		 LIBCERROR_IO_ERROR_CLOSE_FAILED,
652 		 "%s: unable to close file IO handle.",
653 		 function );
654 
655 		result = -1;
656 	}
657 	if( libbfio_handle_free(
658 	     file_io_handle,
659 	     error ) != 1 )
660 	{
661 		libcerror_error_set(
662 		 error,
663 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
664 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
665 		 "%s: unable to free file IO handle.",
666 		 function );
667 
668 		result = -1;
669 	}
670 	return( result );
671 }
672 
673