xreadlink.c (xreadlink): AIX and HP-UX readlink return -1
[gnulib.git] / lib / vasnprintf.c
index e40994d..ff80857 100644 (file)
@@ -1,5 +1,5 @@
 /* vsprintf with automatic memory allocation.
-   Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,7 +40,7 @@
 #include <stdlib.h>    /* abort(), malloc(), realloc(), free() */
 #include <string.h>    /* memcpy(), strlen() */
 #include <errno.h>     /* errno */
-#include <limits.h>    /* CHAR_BIT */
+#include <limits.h>    /* CHAR_BIT, INT_MAX */
 #include <float.h>     /* DBL_MAX_EXP, LDBL_MAX_EXP */
 #if WIDE_CHAR_VERSION
 # include "wprintf-parse.h"
@@ -222,7 +222,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
          {
            size_t augmented_length;
 
-           if (!(dp->arg_index < 0))
+           if (!(dp->arg_index == ARG_NONE))
              abort ();
            augmented_length = xsum (length, 1);
            ENSURE_ALLOCATION (augmented_length);
@@ -231,7 +231,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
          }
        else
          {
-           if (!(dp->arg_index >= 0))
+           if (!(dp->arg_index != ARG_NONE))
              abort ();
 
            if (dp->conversion == 'n')
@@ -279,7 +279,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                  width = 0;
                  if (dp->width_start != dp->width_end)
                    {
-                     if (dp->width_arg_index >= 0)
+                     if (dp->width_arg_index != ARG_NONE)
                        {
                          int arg;
 
@@ -301,7 +301,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                  precision = 6;
                  if (dp->precision_start != dp->precision_end)
                    {
-                     if (dp->precision_arg_index >= 0)
+                     if (dp->precision_arg_index != ARG_NONE)
                        {
                          int arg;
 
@@ -315,9 +315,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                          const CHAR_T *digitp = dp->precision_start + 1;
 
                          precision = 0;
-                         do
+                         while (digitp != dp->precision_end)
                            precision = xsum (xtimes (precision, 10), *digitp++ - '0');
-                         while (digitp != dp->precision_end);
                        }
                    }
 
@@ -563,13 +562,13 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
 
                /* Construct the arguments for calling snprintf or sprintf.  */
                prefix_count = 0;
-               if (dp->width_arg_index >= 0)
+               if (dp->width_arg_index != ARG_NONE)
                  {
                    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
                      abort ();
                    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
                  }
-               if (dp->precision_arg_index >= 0)
+               if (dp->precision_arg_index != ARG_NONE)
                  {
                    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
                      abort ();
@@ -863,8 +862,19 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
       free (buf_malloced);
     CLEANUP ();
     *lengthp = length;
+    if (length > INT_MAX)
+      goto length_overflow;
     return result;
 
+  length_overflow:
+    /* We could produce such a big string, but its length doesn't fit into
+       an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
+       this case.  */
+    if (result != resultbuf)
+      free (result);
+    errno = EOVERFLOW;
+    return NULL;
+
   out_of_memory:
     if (!(result == resultbuf || result == NULL))
       free (result);