]> git.saurik.com Git - apple/libc.git/blobdiff - stdio/FreeBSD/vfwprintf.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfwprintf.c
index 31764a9110e116d0cdd1f0fe36a75adebeb410c7..176a11ca7294b8c0402abe0f85cf46a26d5b3bd3 100644 (file)
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.42 2009/11/25 04:27:55 wo
 #include <errno.h>
 #include "un-namespace.h"
 
+#include <os/assumes.h>
+#include <mach-o/dyld_priv.h>
+
 #include "libc_private.h"
 #include "local.h"
 #include "fvwrite.h"
@@ -373,6 +376,9 @@ vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
        return vfwprintf_l(fp, __current_locale(), fmt0, ap);
 }
 
+// Defined in vfprintf.c
+bool __printf_is_memory_read_only(void *addr, size_t size);
+
 /*
  * The size of the buffer we use as scratch space for integer
  * conversions, among other things.  We need enough space to
@@ -392,14 +398,15 @@ __vfwprintf(FILE *fp, locale_t loc, const wchar_t *fmt0, va_list ap)
 {
        wchar_t *fmt;           /* format string */
        wchar_t ch;             /* character from fmt */
-       int n, n2;              /* handy integer (short term usage) */
+       ssize_t n, n2;          /* handy integer (short term usage) */
        wchar_t *cp;            /* handy char pointer (short term usage) */
        int flags;              /* flags as above */
-       int ret;                /* return value accumulator */
-       int width;              /* width from format (%8d), or 0 */
-       int prec;               /* precision from format; <0 for N/A */
+       ssize_t ret;            /* return value accumulator */
+       ssize_t width;          /* width from format (%8d), or 0 */
+       ssize_t prec;           /* precision from format; <0 for N/A */
        wchar_t sign;           /* sign prefix (' ', '+', '-', or \0) */
        struct grouping_state gs; /* thousands' grouping info */
+
 #ifndef NO_FLOATING_POINT
        /*
         * We can decompose the printed representation of floating
@@ -438,9 +445,9 @@ __vfwprintf(FILE *fp, locale_t loc, const wchar_t *fmt0, va_list ap)
        uintmax_t ujval;        /* %j, %ll, %q, %t, %z integers */
        int base;               /* base for [diouxX] conversion */
        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
-       int realsz;             /* field size expanded by dprec, sign, etc */
-       int size;               /* size of converted field or string */
-       int prsize;             /* max size of printed field */
+       ssize_t realsz;         /* field size expanded by dprec, sign, etc */
+       ssize_t size;           /* size of converted field or string */
+       ssize_t prsize;             /* max size of printed field */
        const char *xdigs;      /* digits for [xX] conversion */
        struct io_state io;     /* I/O buffering state */
        wchar_t buf[BUF];       /* buffer with space for digits of uintmax_t */
@@ -561,8 +568,9 @@ __vfwprintf(FILE *fp, locale_t loc, const wchar_t *fmt0, va_list ap)
                for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
                        /* void */;
                if ((n = fmt - cp) != 0) {
-                       if ((unsigned)ret + n > INT_MAX) {
+                       if (ret + n > INT_MAX) {
                                ret = EOF;
+                               errno = EOVERFLOW;
                                goto error;
                        }
                        PRINT(cp, n);
@@ -771,8 +779,7 @@ reswitch:   switch (ch) {
                                prec = dtoaend - dtoaresult;
                        if (expt == INT_MAX)
                                ox[1] = '\0';
-                       if (convbuf != NULL)
-                               free(convbuf);
+                       free(convbuf);
                        ndig = dtoaend - dtoaresult;
                        cp = convbuf = __mbsconv(dtoaresult, -1, loc);
                        freedtoa(dtoaresult);
@@ -815,8 +822,7 @@ reswitch:   switch (ch) {
 fp_begin:
                        if (prec < 0)
                                prec = DEFPREC;
-                       if (convbuf != NULL)
-                               free(convbuf);
+                       free(convbuf);
                        if (flags & LONGDBL) {
                                fparg.ldbl = GETARG(long double);
                                dtoaresult =
@@ -895,7 +901,8 @@ fp_common:
                        void *ptr = GETARG(void *);
                        if (ptr == NULL)
                                continue;
-                       else if (flags & LLONGINT)
+
+                       if (flags & LLONGINT)
                                *(long long *)ptr = ret;
                        else if (flags & SIZET)
                                *(ssize_t *)ptr = (ssize_t)ret;
@@ -955,11 +962,11 @@ fp_common:
                        } else {
                                char *mbp;
 
-                               if (convbuf != NULL)
-                                       free(convbuf);
-                               if ((mbp = GETARG(char *)) == NULL)
+                               free(convbuf);
+                               if ((mbp = GETARG(char *)) == NULL) {
+                                       convbuf = NULL;
                                        cp = L"(null)";
-                               else {
+                               else {
                                        convbuf = __mbsconv(mbp, prec, loc);
                                        if (convbuf == NULL) {
                                                fp->_flags |= __SERR;
@@ -972,6 +979,11 @@ fp_common:
                        size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
 #else
                        size = wcslen(cp);
+                       if (size >= INT_MAX) {
+                               ret = EOF;
+                               errno = EOVERFLOW;
+                               goto error;
+                       }
                        if(prec >= 0 && prec < size)
                                size = prec;
 #endif
@@ -1046,7 +1058,7 @@ number:                   if ((dprec = prec) >= 0)
                        }
                        size = buf + BUF - cp;
                        if (size > BUF) /* should never happen */
-                               LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+                               LIBC_ABORT("size (%zd) > BUF (%d)", size, BUF);
                        if ((flags & GROUPING) && size != 0)
                                size += grouping_init(&gs, size, loc);
                        break;
@@ -1256,7 +1268,7 @@ number:                   if ((dprec = prec) >= 0)
                break;                                                  \
        }                                                               \
        ret += vlen;                                                    \
-       PRINT(vstr, vlen);                                              \
+       PRINT((const CHAR *) vstr, vlen);                               \
        free(vstr);                                                     \
 } while (0)
 #else /* !V64TYPE */
@@ -1285,7 +1297,7 @@ number:                   if ((dprec = prec) >= 0)
                break;                                                  \
        }                                                               \
        ret += vlen;                                                    \
-       PRINT(vstr, vlen);                                              \
+       PRINT((const CHAR *) vstr, vlen);                               \
        free(vstr);                                                     \
 } while (0)
 #endif /* V64TYPE */
@@ -1369,8 +1381,9 @@ number:                   if ((dprec = prec) >= 0)
                        realsz += 2;
 
                prsize = width > realsz ? width : realsz;
-               if ((unsigned)ret + prsize > INT_MAX) {
+               if (ret + prsize > INT_MAX) {
                        ret = EOF;
+                       errno = EOVERFLOW;
                        goto error;
                }
 
@@ -1455,12 +1468,11 @@ done:
        FLUSH();
 error:
        va_end(orgap);
-       if (convbuf != NULL)
-               free(convbuf);
+       free(convbuf);
        if (__sferror(fp))
                ret = EOF;
        if ((argtable != NULL) && (argtable != statargtable))
                free (argtable);
-       return (ret);
+       return (ret < 0 || ret >= INT_MAX) ? -1 : (int)ret;
        /* NOTREACHED */
 }