Coverage Report

Created: 2024-02-25 07:20

/src/libvsapm/libcerror/libcerror_error.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Error functions
3
 *
4
 * Copyright (C) 2008-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 <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
 */
46
int libcerror_error_initialize(
47
     libcerror_error_t **error,
48
     int error_domain,
49
     int error_code )
50
0
{
51
0
  libcerror_internal_error_t *internal_error = NULL;
52
53
0
  if( error == NULL )
54
0
  {
55
0
    return( -1 );
56
0
  }
57
0
  if( *error != NULL )
58
0
  {
59
0
    return( -1 );
60
0
  }
61
0
  internal_error = memory_allocate_structure(
62
0
                    libcerror_internal_error_t );
63
64
0
  if( internal_error == NULL )
65
0
  {
66
0
    return( -1 );
67
0
  }
68
0
  internal_error->domain             = error_domain;
69
0
  internal_error->code               = error_code;
70
0
  internal_error->number_of_messages = 0;
71
0
  internal_error->messages           = NULL;
72
0
  internal_error->sizes              = NULL;
73
74
0
  *error = (libcerror_error_t *) internal_error;
75
76
0
  return( 1 );
77
0
}
78
79
/* Free an error and its elements
80
 */
81
void libcerror_error_free(
82
      libcerror_error_t **error )
83
233k
{
84
233k
  libcerror_internal_error_t *internal_error = NULL;
85
233k
  int message_index                          = 0;
86
87
233k
  if( error == NULL )
88
233k
  {
89
233k
    return;
90
233k
  }
91
0
  if( *error != NULL )
92
0
  {
93
0
    internal_error = (libcerror_internal_error_t *) *error;
94
95
0
    if( internal_error->messages != NULL )
96
0
    {
97
0
      for( message_index = 0;
98
0
           message_index < internal_error->number_of_messages;
99
0
           message_index++ )
100
0
      {
101
0
        if( internal_error->messages[ message_index ] != NULL )
102
0
        {
103
0
          memory_free(
104
0
           internal_error->messages[ message_index ] );
105
0
        }
106
0
      }
107
0
      memory_free(
108
0
       internal_error->messages );
109
0
    }
110
0
    if( internal_error->sizes != NULL )
111
0
    {
112
0
      memory_free(
113
0
       internal_error->sizes );
114
0
    }
115
0
    memory_free(
116
0
     *error );
117
118
0
    *error = NULL;
119
0
  }
120
0
}
121
122
/* Resizes an error
123
 * Returns 1 if successful or -1 on error
124
 */
125
int libcerror_error_resize(
126
     libcerror_internal_error_t *internal_error )
127
0
{
128
0
  void *reallocation     = NULL;
129
0
  int message_index      = 0;
130
0
  int number_of_messages = 0;
131
132
0
  if( internal_error == NULL )
133
0
  {
134
0
    return( -1 );
135
0
  }
136
0
  message_index      = internal_error->number_of_messages;
137
0
  number_of_messages = internal_error->number_of_messages + 1;
138
139
0
  reallocation = memory_reallocate(
140
0
                  internal_error->messages,
141
0
                  sizeof( system_character_t * ) * number_of_messages );
142
143
0
  if( reallocation == NULL )
144
0
  {
145
0
    return( -1 );
146
0
  }
147
0
  internal_error->messages = (system_character_t **) reallocation;
148
149
0
  internal_error->messages[ message_index ] = NULL;
150
151
0
  reallocation = memory_reallocate(
152
0
                  internal_error->sizes,
153
0
                  sizeof( size_t ) * number_of_messages );
154
155
0
  if( reallocation == NULL )
156
0
  {
157
0
    return( -1 );
158
0
  }
159
0
  internal_error->sizes = (size_t *) reallocation;
160
161
0
  internal_error->sizes[ message_index ] = 0;
162
163
0
  internal_error->number_of_messages += 1;
164
165
0
  return( 1 );
166
0
}
167
168
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
169
170
/* Retrieves the format string as a system string
171
 */
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
0
        va_start( argument_list, name )
290
#define VAEND( argument_list ) \
291
0
        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
 */
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
1.61M
{
315
1.61M
  va_list argument_list;
316
317
1.61M
  libcerror_internal_error_t *internal_error = NULL;
318
1.61M
  system_character_t *error_string           = NULL;
319
1.61M
  system_character_t *system_format_string   = NULL;
320
1.61M
  void *reallocation                         = NULL;
321
1.61M
  size_t error_string_size                   = 0;
322
1.61M
  size_t format_string_length                = 0;
323
1.61M
  size_t message_size                        = 0;
324
1.61M
  size_t next_message_size                   = LIBCERROR_MESSAGE_INCREMENT_SIZE;
325
1.61M
  int message_index                          = 0;
326
1.61M
  int print_count                            = 0;
327
328
1.61M
  if( error == NULL )
329
1.61M
  {
330
1.61M
    return;
331
1.61M
  }
332
0
  if( format_string == NULL )
333
0
  {
334
0
    return;
335
0
  }
336
0
  format_string_length = narrow_string_length(
337
0
                          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
0
  system_format_string = (system_character_t *) format_string;
351
0
#endif
352
0
  if( *error == NULL )
353
0
  {
354
0
    if( libcerror_error_initialize(
355
0
         error,
356
0
         error_domain,
357
0
         error_code ) != 1 )
358
0
    {
359
0
      goto on_error;
360
0
    }
361
0
  }
362
0
  internal_error = (libcerror_internal_error_t *) *error;
363
364
0
  if( libcerror_error_resize(
365
0
       internal_error ) != 1 )
366
0
  {
367
0
    goto on_error;
368
0
  }
369
0
  if( format_string_length > next_message_size )
370
0
  {
371
0
    next_message_size = ( ( format_string_length / LIBCERROR_MESSAGE_INCREMENT_SIZE ) + 1 )
372
0
                      * LIBCERROR_MESSAGE_INCREMENT_SIZE;
373
0
  }
374
0
  do
375
0
  {
376
0
    if( next_message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
377
0
    {
378
0
      next_message_size = LIBCERROR_MESSAGE_MAXIMUM_SIZE;
379
0
    }
380
0
    reallocation = memory_reallocate(
381
0
                    error_string,
382
0
                    sizeof( system_character_t ) * next_message_size );
383
384
0
    if( reallocation == NULL )
385
0
    {
386
0
      memory_free(
387
0
       error_string );
388
389
0
      goto on_error;
390
0
    }
391
0
    error_string = (system_character_t *) reallocation;
392
393
0
    message_size = next_message_size;
394
395
    /* argument_list cannot be reused in successive calls to vsnprintf
396
     */
397
0
    VASTART(
398
0
     argument_list,
399
0
     const char *,
400
0
     format_string );
401
402
0
    print_count = system_string_vsnprintf(
403
0
                   error_string,
404
0
                   message_size,
405
0
                   system_format_string,
406
0
                   argument_list );
407
408
0
    VAEND(
409
0
     argument_list );
410
411
0
    if( print_count <= -1 )
412
0
    {
413
0
      next_message_size += LIBCERROR_MESSAGE_INCREMENT_SIZE;
414
0
    }
415
0
    else if( ( (size_t) print_count >= message_size )
416
0
          || ( error_string[ print_count ] != (system_character_t) 0 ) )
417
0
    {
418
0
      next_message_size = (size_t) ( print_count + 1 );
419
0
      print_count       = -1;
420
0
    }
421
0
    else
422
0
    {
423
0
      error_string_size = (size_t) print_count + 1;
424
0
    }
425
0
    if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
426
0
    {
427
0
      break;
428
0
    }
429
0
  }
430
0
  while( print_count <= -1 );
431
432
0
  if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
433
0
  {
434
0
    error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 4 ] = (system_character_t) '.';
435
0
    error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 3 ] = (system_character_t) '.';
436
0
    error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 2 ] = (system_character_t) '.';
437
0
    error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 1 ] = 0;
438
0
    error_string_size                                  = (size_t) LIBCERROR_MESSAGE_MAXIMUM_SIZE;
439
0
  }
440
0
  message_index = internal_error->number_of_messages - 1;
441
442
0
  internal_error->messages[ message_index ] = error_string;
443
0
  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
0
  return;
452
453
0
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
0
  return;
462
0
}
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
 */
471
int libcerror_error_matches(
472
     libcerror_error_t *error,
473
     int error_domain,
474
     int error_code )
475
0
{
476
0
  if( error == NULL )
477
0
  {
478
0
    return( 0 );
479
0
  }
480
0
  if( ( ( (libcerror_internal_error_t *) error )->domain == error_domain )
481
0
   && ( ( (libcerror_internal_error_t *) error )->code == error_code ) )
482
0
  {
483
0
    return( 1 );
484
0
  }
485
0
  return( 0 );
486
0
}
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
 */
491
int libcerror_error_fprint(
492
     libcerror_error_t *error,
493
     FILE *stream )
494
0
{
495
0
  libcerror_internal_error_t *internal_error = NULL;
496
0
  system_character_t *error_string           = NULL;
497
0
  int message_index                          = 0;
498
0
  int print_count                            = 0;
499
500
#if defined( WINAPI )
501
  const char *format_string                  = "%" PRIs_SYSTEM "\r\n";
502
#else
503
0
  const char *format_string                  = "%" PRIs_SYSTEM "\n";
504
0
#endif
505
506
0
  if( error == NULL )
507
0
  {
508
0
    return( -1 );
509
0
  }
510
0
  internal_error = (libcerror_internal_error_t *) error;
511
512
0
  if( internal_error->messages == NULL )
513
0
  {
514
0
    return( -1 );
515
0
  }
516
0
  if( stream == NULL )
517
0
  {
518
0
    return( -1 );
519
0
  }
520
0
  message_index = internal_error->number_of_messages - 1;
521
0
  error_string  = internal_error->messages[ message_index ];
522
523
0
  if( error_string != NULL )
524
0
  {
525
0
    print_count = fprintf(
526
0
                   stream,
527
0
                   format_string,
528
0
                   error_string );
529
530
0
    if( print_count <= -1 )
531
0
    {
532
0
      return( -1 );
533
0
    }
534
0
  }
535
0
  return( print_count );
536
0
}
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
 */
542
int libcerror_error_sprint(
543
     libcerror_error_t *error,
544
     char *string,
545
     size_t size )
546
0
{
547
0
  libcerror_internal_error_t *internal_error = NULL;
548
0
  system_character_t *error_string           = NULL;
549
0
  size_t message_index                       = 0;
550
0
  size_t print_count                         = 0;
551
552
0
#if !defined( HAVE_WIDE_SYSTEM_CHARACTER )
553
0
  size_t error_string_size                   = 0;
554
0
#endif
555
556
0
  if( error == NULL )
557
0
  {
558
0
    return( -1 );
559
0
  }
560
0
  internal_error = (libcerror_internal_error_t *) error;
561
562
0
  if( internal_error->messages == NULL )
563
0
  {
564
0
    return( -1 );
565
0
  }
566
0
  if( internal_error->sizes == NULL )
567
0
  {
568
0
    return( -1 );
569
0
  }
570
0
  if( string == NULL )
571
0
  {
572
0
    return( -1 );
573
0
  }
574
0
#if INT_MAX < SSIZE_MAX
575
0
  if( size > (size_t) INT_MAX )
576
#else
577
  if( size > (size_t) SSIZE_MAX )
578
#endif
579
0
  {
580
0
    return( -1 );
581
0
  }
582
0
  message_index = internal_error->number_of_messages - 1;
583
0
  error_string  = internal_error->messages[ message_index ];
584
585
0
  if( error_string != NULL )
586
0
  {
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
0
    error_string_size = internal_error->sizes[ message_index ];
616
617
0
    if( size < ( error_string_size + 1 ) )
618
0
    {
619
0
      return( -1 );
620
0
    }
621
0
    if( narrow_string_copy(
622
0
         string,
623
0
         error_string,
624
0
         error_string_size ) == NULL )
625
0
    {
626
0
      return( -1 );
627
0
    }
628
0
    print_count = error_string_size;
629
630
0
#endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
631
0
  }
632
0
  if( print_count > (size_t) INT_MAX )
633
0
  {
634
0
    return( -1 );
635
0
  }
636
0
  return( (int) print_count );
637
0
}
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
 */
642
int libcerror_error_backtrace_fprint(
643
     libcerror_error_t *error,
644
     FILE *stream )
645
0
{
646
0
  libcerror_internal_error_t *internal_error = NULL;
647
0
  system_character_t *error_string           = NULL;
648
0
  int message_index                          = 0;
649
0
  int print_count                            = 0;
650
0
  int total_print_count                      = 0;
651
652
#if defined( WINAPI )
653
  const char *format_string                  = "%" PRIs_SYSTEM "\r\n";
654
#else
655
0
  const char *format_string                  = "%" PRIs_SYSTEM "\n";
656
0
#endif
657
658
0
  if( error == NULL )
659
0
  {
660
0
    return( -1 );
661
0
  }
662
0
  internal_error = (libcerror_internal_error_t *) error;
663
664
0
  if( internal_error->messages == NULL )
665
0
  {
666
0
    return( -1 );
667
0
  }
668
0
  if( stream == NULL )
669
0
  {
670
0
    return( -1 );
671
0
  }
672
0
  for( message_index = 0;
673
0
       message_index < internal_error->number_of_messages;
674
0
       message_index++ )
675
0
  {
676
0
    error_string = internal_error->messages[ message_index ];
677
678
0
    if( error_string != NULL )
679
0
    {
680
0
      print_count = fprintf(
681
0
                     stream,
682
0
                     format_string,
683
0
                     error_string );
684
685
0
      if( print_count <= -1 )
686
0
      {
687
0
        return( -1 );
688
0
      }
689
0
      total_print_count += print_count;
690
0
    }
691
0
  }
692
0
  return( total_print_count );
693
0
}
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
 */
699
int libcerror_error_backtrace_sprint(
700
     libcerror_error_t *error,
701
     char *string,
702
     size_t size )
703
0
{
704
0
  libcerror_internal_error_t *internal_error = NULL;
705
0
  system_character_t *error_string           = NULL;
706
0
  size_t string_index                        = 0;
707
0
  int message_index                          = 0;
708
709
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
710
  size_t print_count                         = 0;
711
#else
712
0
  size_t error_string_size                   = 0;
713
0
#endif
714
715
0
  if( error == NULL )
716
0
  {
717
0
    return( -1 );
718
0
  }
719
0
  internal_error = (libcerror_internal_error_t *) error;
720
721
0
  if( internal_error->messages == NULL )
722
0
  {
723
0
    return( -1 );
724
0
  }
725
0
  if( internal_error->sizes == NULL )
726
0
  {
727
0
    return( -1 );
728
0
  }
729
0
  if( string == NULL )
730
0
  {
731
0
    return( -1 );
732
0
  }
733
0
#if INT_MAX < SSIZE_MAX
734
0
  if( size > (size_t) INT_MAX )
735
#else
736
  if( size > (size_t) SSIZE_MAX )
737
#endif
738
0
  {
739
0
    return( -1 );
740
0
  }
741
0
  for( message_index = 0;
742
0
       message_index < internal_error->number_of_messages;
743
0
       message_index++ )
744
0
  {
745
0
    error_string = internal_error->messages[ message_index ];
746
747
0
    if( error_string != NULL )
748
0
    {
749
0
      if( string_index > 0 )
750
0
      {
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
0
        if( ( string_index + 1 ) >= size )
759
0
        {
760
0
          return( -1 );
761
0
        }
762
0
#endif /* defined( WINAPI ) */
763
764
0
        string[ string_index++ ] = (system_character_t) '\n';
765
0
        string[ string_index ]   = (system_character_t) 0;
766
0
      }
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
0
      error_string_size = internal_error->sizes[ message_index ];
802
803
0
      if( size < ( string_index + error_string_size + 1 ) )
804
0
      {
805
0
        return( -1 );
806
0
      }
807
0
      if( narrow_string_copy(
808
0
           &( string[ string_index ] ),
809
0
           error_string,
810
0
           error_string_size ) == NULL )
811
0
      {
812
0
        return( -1 );
813
0
      }
814
0
      string_index += error_string_size - 1;
815
816
0
#endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
817
0
    }
818
0
  }
819
0
  string_index++;
820
821
0
  if( string_index > (size_t) INT_MAX )
822
0
  {
823
0
    return( -1 );
824
0
  }
825
0
  return( (int) string_index );
826
0
}
827