1 /*
2  * Error functions
3  *
4  * Copyright (C) 2008-2020, 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 <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28 
29 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
30 #include <stdarg.h>
31 #elif defined( HAVE_VARARGS_H )
32 #include <varargs.h>
33 #else
34 #error Missing headers stdarg.h and varargs.h
35 #endif
36 
37 #include <errno.h>
38 
39 #include "libcerror_definitions.h"
40 #include "libcerror_error.h"
41 #include "libcerror_types.h"
42 
43 /* Creates an error
44  * Returns 1 if successful or -1 on error
45  */
libcerror_error_initialize(libcerror_error_t ** error,int error_domain,int error_code)46 int libcerror_error_initialize(
47      libcerror_error_t **error,
48      int error_domain,
49      int error_code )
50 {
51 	libcerror_internal_error_t *internal_error = NULL;
52 
53 	if( error == NULL )
54 	{
55 		return( -1 );
56 	}
57 	if( *error != NULL )
58 	{
59 		return( -1 );
60 	}
61 	internal_error = memory_allocate_structure(
62 	                  libcerror_internal_error_t );
63 
64 	if( internal_error == NULL )
65 	{
66 		return( -1 );
67 	}
68 	internal_error->domain             = error_domain;
69 	internal_error->code               = error_code;
70 	internal_error->number_of_messages = 0;
71 	internal_error->messages           = NULL;
72 	internal_error->sizes              = NULL;
73 
74 	*error = (libcerror_error_t *) internal_error;
75 
76 	return( 1 );
77 }
78 
79 /* Free an error and its elements
80  */
libcerror_error_free(libcerror_error_t ** error)81 void libcerror_error_free(
82       libcerror_error_t **error )
83 {
84 	libcerror_internal_error_t *internal_error = NULL;
85 	int message_index                          = 0;
86 
87 	if( error == NULL )
88 	{
89 		return;
90 	}
91 	if( *error != NULL )
92 	{
93 		internal_error = (libcerror_internal_error_t *) *error;
94 
95 		if( internal_error->messages != NULL )
96 		{
97 			for( message_index = 0;
98 			     message_index < internal_error->number_of_messages;
99 			     message_index++ )
100 			{
101 				if( internal_error->messages[ message_index ] != NULL )
102 				{
103 					memory_free(
104 					 internal_error->messages[ message_index ] );
105 				}
106 			}
107 			memory_free(
108 			 internal_error->messages );
109 		}
110 		if( internal_error->sizes != NULL )
111 		{
112 			memory_free(
113 			 internal_error->sizes );
114 		}
115 		memory_free(
116 		 *error );
117 
118 		*error = NULL;
119 	}
120 }
121 
122 /* Resizes an error
123  * Returns 1 if successful or -1 on error
124  */
libcerror_error_resize(libcerror_internal_error_t * internal_error)125 int libcerror_error_resize(
126      libcerror_internal_error_t *internal_error )
127 {
128 	void *reallocation     = NULL;
129 	int message_index      = 0;
130 	int number_of_messages = 0;
131 
132 	if( internal_error == NULL )
133 	{
134 		return( -1 );
135 	}
136 	message_index      = internal_error->number_of_messages;
137 	number_of_messages = internal_error->number_of_messages + 1;
138 
139 	reallocation = memory_reallocate(
140 	                internal_error->messages,
141 	                sizeof( system_character_t * ) * number_of_messages );
142 
143 	if( reallocation == NULL )
144 	{
145 		return( -1 );
146 	}
147 	internal_error->messages = (system_character_t **) reallocation;
148 
149 	internal_error->messages[ message_index ] = NULL;
150 
151 	reallocation = memory_reallocate(
152 	                internal_error->sizes,
153 	                sizeof( size_t ) * number_of_messages );
154 
155 	if( reallocation == NULL )
156 	{
157 		return( -1 );
158 	}
159 	internal_error->sizes = (size_t *) reallocation;
160 
161 	internal_error->sizes[ message_index ] = 0;
162 
163 	internal_error->number_of_messages += 1;
164 
165 	return( 1 );
166 }
167 
168 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
169 
170 /* Retrieves the format string as a system string
171  */
libcerror_error_get_system_format_string(const char * format_string,size_t format_string_length,system_character_t ** system_format_string)172 void libcerror_error_get_system_format_string(
173       const char *format_string,
174       size_t format_string_length,
175       system_character_t **system_format_string )
176 {
177 	void *reallocation               = NULL;
178 	size_t next_format_string_length = 0;
179 	int print_count                  = 0;
180 
181 #if defined( __BORLANDC__ ) || defined( _MSC_VER )
182 	size_t string_index              = 0;
183 #endif
184 
185 	if( format_string == NULL )
186 	{
187 		return;
188 	}
189 	if( format_string_length > (size_t) SSIZE_MAX )
190 	{
191 		return;
192 	}
193 	if( system_format_string == NULL )
194 	{
195 		return;
196 	}
197 	next_format_string_length = format_string_length + 1;
198 
199 	do
200 	{
201 		if( next_format_string_length >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
202 		{
203 			next_format_string_length = LIBCERROR_MESSAGE_MAXIMUM_SIZE;
204 		}
205 		reallocation = memory_reallocate(
206 		                *system_format_string,
207 		                sizeof( system_character_t ) * next_format_string_length );
208 
209 		if( reallocation == NULL )
210 		{
211 			memory_free(
212 			 *system_format_string );
213 
214 			*system_format_string = NULL;
215 
216 			return;
217 		}
218 		*system_format_string = (system_character_t *) reallocation;
219 
220 		format_string_length = next_format_string_length;
221 
222 #if defined( __BORLANDC__ ) || defined( _MSC_VER )
223 		print_count = wide_string_snwprintf(
224 		               *system_format_string,
225 		               format_string_length,
226 		               L"%S",
227 		               format_string );
228 #else
229 		print_count = wide_string_snwprintf(
230 		               *system_format_string,
231 		               format_string_length,
232 		               L"%s",
233 		               format_string );
234 #endif
235 		if( print_count <= -1 )
236 		{
237 			next_format_string_length += LIBCERROR_MESSAGE_INCREMENT_SIZE;
238 		}
239 		else if( ( (size_t) print_count > format_string_length )
240 		      || ( ( *system_format_string )[ print_count ] != 0 ) )
241 		{
242 			next_format_string_length = (size_t) print_count;
243 			print_count               = -1;
244 		}
245 		if( next_format_string_length >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
246 		{
247 /* TODO handle similar to error string */
248 			memory_free(
249 			 *system_format_string );
250 
251 			*system_format_string = NULL;
252 
253 			return;
254 		}
255 	}
256 	while( print_count <= -1 );
257 
258 #if defined( __BORLANDC__ ) || defined( _MSC_VER )
259 	/* Rewrite %s to %S
260 	 */
261 	string_index = 0;
262 
263 	while( string_index < format_string_length )
264 	{
265 		if( ( *system_format_string )[ string_index ] == 0 )
266 		{
267 			break;
268 		}
269 		else if( ( *system_format_string )[ string_index ] == (system_character_t) '%' )
270 		{
271 			string_index++;
272 
273 			if( ( *system_format_string )[ string_index ] == (system_character_t) 's' )
274 			{
275 				 ( *system_format_string )[ string_index ] = (system_character_t) 'S';
276 			}
277 		}
278 		string_index++;
279 	}
280 #endif /* defined( __BORLANDC__ ) || defined( _MSC_VER ) */
281 }
282 
283 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
284 
285 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
286 #define VARARGS( function, error, error_domain, error_code, type, argument ) \
287         function( error, error_domain, error_code, type argument, ... )
288 #define VASTART( argument_list, type, name ) \
289         va_start( argument_list, name )
290 #define VAEND( argument_list ) \
291         va_end( argument_list )
292 
293 #elif defined( HAVE_VARARGS_H )
294 #define VARARGS( function, error, error_domain, error_code, type, argument ) \
295         function( error, error_domain, error_code, va_alist ) va_dcl
296 #define VASTART( argument_list, type, name ) \
297         { type name; va_start( argument_list ); name = va_arg( argument_list, type )
298 #define VAEND( argument_list ) \
299         va_end( argument_list ); }
300 
301 #endif /* defined( HAVE_STDARG_H ) || defined( WINAPI ) */
302 
303 /* Sets an error
304  * Creates the error if necessary
305  * The error domain and code are set only the first time and the error message is appended for back tracing
306  */
VARARGS(libcerror_error_set,libcerror_error_t ** error,int error_domain,int error_code,const char *,format_string)307 void VARARGS(
308       libcerror_error_set,
309       libcerror_error_t **error,
310       int error_domain,
311       int error_code,
312       const char *,
313       format_string )
314 {
315 	va_list argument_list;
316 
317 	libcerror_internal_error_t *internal_error = NULL;
318 	system_character_t *error_string           = NULL;
319 	system_character_t *system_format_string   = NULL;
320 	void *reallocation                         = NULL;
321 	size_t error_string_size                   = 0;
322 	size_t format_string_length                = 0;
323 	size_t message_size                        = 0;
324 	size_t next_message_size                   = LIBCERROR_MESSAGE_INCREMENT_SIZE;
325 	int message_index                          = 0;
326 	int print_count                            = 0;
327 
328 	if( error == NULL )
329 	{
330 		return;
331 	}
332 	if( format_string == NULL )
333 	{
334 		return;
335 	}
336 	format_string_length = narrow_string_length(
337 	                        format_string );
338 
339 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
340 	libcerror_error_get_system_format_string(
341 	 format_string,
342 	 format_string_length,
343 	 &system_format_string );
344 
345 	if( system_format_string == NULL )
346 	{
347 		return;
348 	}
349 #else
350 	system_format_string = (system_character_t *) format_string;
351 #endif
352 	if( *error == NULL )
353 	{
354 		if( libcerror_error_initialize(
355 		     error,
356 		     error_domain,
357 		     error_code ) != 1 )
358 		{
359 			goto on_error;
360 		}
361 	}
362 	internal_error = (libcerror_internal_error_t *) *error;
363 
364 	if( libcerror_error_resize(
365 	     internal_error ) != 1 )
366 	{
367 		goto on_error;
368 	}
369 	if( format_string_length > next_message_size )
370 	{
371 		next_message_size = ( ( format_string_length / LIBCERROR_MESSAGE_INCREMENT_SIZE ) + 1 )
372 		                  * LIBCERROR_MESSAGE_INCREMENT_SIZE;
373 	}
374 	do
375 	{
376 		if( next_message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
377 		{
378 			next_message_size = LIBCERROR_MESSAGE_MAXIMUM_SIZE;
379 		}
380 		reallocation = memory_reallocate(
381 		                error_string,
382 		                sizeof( system_character_t ) * next_message_size );
383 
384 		if( reallocation == NULL )
385 		{
386 			memory_free(
387 			 error_string );
388 
389 			goto on_error;
390 		}
391 		error_string = (system_character_t *) reallocation;
392 
393 		message_size = next_message_size;
394 
395 		/* argument_list cannot be reused in successive calls to vsnprintf
396 		 */
397 		VASTART(
398 		 argument_list,
399 		 const char *,
400 		 format_string );
401 
402 		print_count = system_string_vsnprintf(
403 		               error_string,
404 		               message_size,
405 		               system_format_string,
406 		               argument_list );
407 
408 		VAEND(
409 		 argument_list );
410 
411 		if( print_count <= -1 )
412 		{
413 			next_message_size += LIBCERROR_MESSAGE_INCREMENT_SIZE;
414 		}
415 		else if( ( (size_t) print_count >= message_size )
416 		      || ( error_string[ print_count ] != (system_character_t) 0 ) )
417 		{
418 			next_message_size = (size_t) ( print_count + 1 );
419 			print_count       = -1;
420 		}
421 		else
422 		{
423 			error_string_size = (size_t) print_count + 1;
424 		}
425 		if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
426 		{
427 			break;
428 		}
429 	}
430 	while( print_count <= -1 );
431 
432 	if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
433 	{
434 		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 4 ] = (system_character_t) '.';
435 		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 3 ] = (system_character_t) '.';
436 		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 2 ] = (system_character_t) '.';
437 		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 1 ] = 0;
438 		error_string_size                                  = (size_t) LIBCERROR_MESSAGE_MAXIMUM_SIZE;
439 	}
440 	message_index = internal_error->number_of_messages - 1;
441 
442 	internal_error->messages[ message_index ] = error_string;
443 	internal_error->sizes[ message_index ]    = error_string_size;
444 
445 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
446 	memory_free(
447 	 system_format_string );
448 
449 	system_format_string = NULL;
450 #endif
451 	return;
452 
453 on_error:
454 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
455 	if( system_format_string != NULL )
456 	{
457 		memory_free(
458 		 system_format_string );
459 	}
460 #endif
461 	return;
462 }
463 
464 #undef VARARGS
465 #undef VASTART
466 #undef VAEND
467 
468 /* Determines if an error equals a certain error code of a domain
469  * Returns 1 if error matches or 0 if not
470  */
libcerror_error_matches(libcerror_error_t * error,int error_domain,int error_code)471 int libcerror_error_matches(
472      libcerror_error_t *error,
473      int error_domain,
474      int error_code )
475 {
476 	if( error == NULL )
477 	{
478 		return( 0 );
479 	}
480 	if( ( ( (libcerror_internal_error_t *) error )->domain == error_domain )
481 	 && ( ( (libcerror_internal_error_t *) error )->code == error_code ) )
482 	{
483 		return( 1 );
484 	}
485 	return( 0 );
486 }
487 
488 /* Prints a descriptive string of the error to the stream
489  * Returns the number of printed characters if successful or -1 on error
490  */
libcerror_error_fprint(libcerror_error_t * error,FILE * stream)491 int libcerror_error_fprint(
492      libcerror_error_t *error,
493      FILE *stream )
494 {
495 	libcerror_internal_error_t *internal_error = NULL;
496 	system_character_t *error_string           = NULL;
497 	int message_index                          = 0;
498 	int print_count                            = 0;
499 
500 #if defined( WINAPI )
501 	const char *format_string                  = "%" PRIs_SYSTEM "\r\n";
502 #else
503 	const char *format_string                  = "%" PRIs_SYSTEM "\n";
504 #endif
505 
506 	if( error == NULL )
507 	{
508 		return( -1 );
509 	}
510 	internal_error = (libcerror_internal_error_t *) error;
511 
512 	if( internal_error->messages == NULL )
513 	{
514 		return( -1 );
515 	}
516 	if( stream == NULL )
517 	{
518 		return( -1 );
519 	}
520 	message_index = internal_error->number_of_messages - 1;
521 	error_string  = internal_error->messages[ message_index ];
522 
523 	if( error_string != NULL )
524 	{
525 		print_count = fprintf(
526 		               stream,
527 		               format_string,
528 		               error_string );
529 
530 		if( print_count <= -1 )
531 		{
532 			return( -1 );
533 		}
534 	}
535 	return( print_count );
536 }
537 
538 /* Prints a descriptive string of the error to the string
539  * The end-of-string character is not included in the return value
540  * Returns the number of printed characters if successful or -1 on error
541  */
libcerror_error_sprint(libcerror_error_t * error,char * string,size_t size)542 int libcerror_error_sprint(
543      libcerror_error_t *error,
544      char *string,
545      size_t size )
546 {
547 	libcerror_internal_error_t *internal_error = NULL;
548 	system_character_t *error_string           = NULL;
549 	size_t message_index                       = 0;
550 	size_t print_count                         = 0;
551 
552 #if !defined( HAVE_WIDE_SYSTEM_CHARACTER )
553 	size_t error_string_size                   = 0;
554 #endif
555 
556 	if( error == NULL )
557 	{
558 		return( -1 );
559 	}
560 	internal_error = (libcerror_internal_error_t *) error;
561 
562 	if( internal_error->messages == NULL )
563 	{
564 		return( -1 );
565 	}
566 	if( internal_error->sizes == NULL )
567 	{
568 		return( -1 );
569 	}
570 	if( string == NULL )
571 	{
572 		return( -1 );
573 	}
574 #if INT_MAX < SSIZE_MAX
575 	if( size > (size_t) INT_MAX )
576 #else
577 	if( size > (size_t) SSIZE_MAX )
578 #endif
579 	{
580 		return( -1 );
581 	}
582 	message_index = internal_error->number_of_messages - 1;
583 	error_string  = internal_error->messages[ message_index ];
584 
585 	if( error_string != NULL )
586 	{
587 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
588 #if defined( _MSC_VER )
589 		if( wcstombs_s(
590 		     &print_count,
591 		     string,
592 		     size,
593 		     error_string,
594 		     _TRUNCATE ) != 0 )
595 		{
596 			return( -1 );
597 		}
598 #else
599 		print_count = wcstombs(
600 		               string,
601 		               error_string,
602 		               size );
603 
604 		if( print_count == (size_t) -1 )
605 		{
606 			return( -1 );
607 		}
608 #endif /* defined( _MSC_VER ) */
609 
610 		if( print_count >= size )
611 		{
612 			return( -1 );
613 		}
614 #else
615 		error_string_size = internal_error->sizes[ message_index ];
616 
617 		if( size < ( error_string_size + 1 ) )
618 		{
619 			return( -1 );
620 		}
621 		if( narrow_string_copy(
622 		     string,
623 		     error_string,
624 		     error_string_size ) == NULL )
625 		{
626 			return( -1 );
627 		}
628 		print_count = error_string_size;
629 
630 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
631 	}
632 	if( print_count > (size_t) INT_MAX )
633 	{
634 		return( -1 );
635 	}
636 	return( (int) print_count );
637 }
638 
639 /* Prints a backtrace of the error to the stream
640  * Returns the number of printed characters if successful or -1 on error
641  */
libcerror_error_backtrace_fprint(libcerror_error_t * error,FILE * stream)642 int libcerror_error_backtrace_fprint(
643      libcerror_error_t *error,
644      FILE *stream )
645 {
646 	libcerror_internal_error_t *internal_error = NULL;
647 	system_character_t *error_string           = NULL;
648 	int message_index                          = 0;
649 	int print_count                            = 0;
650 	int total_print_count                      = 0;
651 
652 #if defined( WINAPI )
653 	const char *format_string                  = "%" PRIs_SYSTEM "\r\n";
654 #else
655 	const char *format_string                  = "%" PRIs_SYSTEM "\n";
656 #endif
657 
658 	if( error == NULL )
659 	{
660 		return( -1 );
661 	}
662 	internal_error = (libcerror_internal_error_t *) error;
663 
664 	if( internal_error->messages == NULL )
665 	{
666 		return( -1 );
667 	}
668 	if( stream == NULL )
669 	{
670 		return( -1 );
671 	}
672 	for( message_index = 0;
673 	     message_index < internal_error->number_of_messages;
674 	     message_index++ )
675 	{
676 		error_string = internal_error->messages[ message_index ];
677 
678 		if( error_string != NULL )
679 		{
680 			print_count = fprintf(
681 			               stream,
682 			               format_string,
683 			               error_string );
684 
685 			if( print_count <= -1 )
686 			{
687 				return( -1 );
688 			}
689 			total_print_count += print_count;
690 		}
691 	}
692 	return( total_print_count );
693 }
694 
695 /* Prints a backtrace of the error to the string
696  * The end-of-string character is not included in the return value
697  * Returns the number of printed characters if successful or -1 on error
698  */
libcerror_error_backtrace_sprint(libcerror_error_t * error,char * string,size_t size)699 int libcerror_error_backtrace_sprint(
700      libcerror_error_t *error,
701      char *string,
702      size_t size )
703 {
704 	libcerror_internal_error_t *internal_error = NULL;
705 	system_character_t *error_string           = NULL;
706 	size_t string_index                        = 0;
707 	int message_index                          = 0;
708 
709 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
710 	size_t print_count                         = 0;
711 #else
712 	size_t error_string_size                   = 0;
713 #endif
714 
715 	if( error == NULL )
716 	{
717 		return( -1 );
718 	}
719 	internal_error = (libcerror_internal_error_t *) error;
720 
721 	if( internal_error->messages == NULL )
722 	{
723 		return( -1 );
724 	}
725 	if( internal_error->sizes == NULL )
726 	{
727 		return( -1 );
728 	}
729 	if( string == NULL )
730 	{
731 		return( -1 );
732 	}
733 #if INT_MAX < SSIZE_MAX
734 	if( size > (size_t) INT_MAX )
735 #else
736 	if( size > (size_t) SSIZE_MAX )
737 #endif
738 	{
739 		return( -1 );
740 	}
741 	for( message_index = 0;
742 	     message_index < internal_error->number_of_messages;
743 	     message_index++ )
744 	{
745 		error_string = internal_error->messages[ message_index ];
746 
747 		if( error_string != NULL )
748 		{
749 			if( string_index > 0 )
750 			{
751 #if defined( WINAPI )
752 				if( ( string_index + 2 ) >= size )
753 				{
754 					return( -1 );
755 				}
756 				string[ string_index++ ] = (system_character_t) '\r';
757 #else
758 				if( ( string_index + 1 ) >= size )
759 				{
760 					return( -1 );
761 				}
762 #endif /* defined( WINAPI ) */
763 
764 				string[ string_index++ ] = (system_character_t) '\n';
765 				string[ string_index ]   = (system_character_t) 0;
766 			}
767 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
768 #if defined( _MSC_VER )
769 			if( wcstombs_s(
770 			     &print_count,
771 			     &( string[ string_index ] ),
772 			     size - string_index,
773 			     error_string,
774 			     _TRUNCATE ) != 0 )
775 			{
776 				return( -1 );
777 			}
778 #else
779 			print_count = wcstombs(
780 			               &( string[ string_index ] ),
781 			               error_string,
782 			               size - string_index );
783 
784 			if( print_count == (size_t) -1 )
785 			{
786 				return( -1 );
787 			}
788 #endif /*defined( _MSC_VER ) */
789 
790 			string_index += print_count;
791 
792 			if( string_index >= size )
793 			{
794 				return( -1 );
795 			}
796 			if( string[ string_index - 1 ] == 0 )
797 			{
798 				string_index--;
799 			}
800 #else
801 			error_string_size = internal_error->sizes[ message_index ];
802 
803 			if( size < ( string_index + error_string_size + 1 ) )
804 			{
805 				return( -1 );
806 			}
807 			if( narrow_string_copy(
808 			     &( string[ string_index ] ),
809 			     error_string,
810 			     error_string_size ) == NULL )
811 			{
812 				return( -1 );
813 			}
814 			string_index += error_string_size - 1;
815 
816 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
817 		}
818 	}
819 	string_index++;
820 
821 	if( string_index > (size_t) INT_MAX )
822 	{
823 		return( -1 );
824 	}
825 	return( (int) string_index );
826 }
827 
828