1 /*	$OpenBSD: vfscanf.c,v 1.31 2014/03/19 05:17:01 guenther Exp $ */
2 /*-
3  * Copyright (c) 1990, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Chris Torek.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <ctype.h>
35 #include <inttypes.h>
36 #include <limits.h>
37 #include <locale.h>
38 #include <stdarg.h>
39 #include <stddef.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/param.h>
44 #include <wctype.h>
45 #include "local.h"
46 
47 #include <platform/bionic/macros.h>
48 #include <private/bionic_fortify.h>
49 #include <private/bionic_mbstate.h>
50 
51 #define BUF 513 /* Maximum length of numeric string. */
52 
53 // Flags used during conversion.
54 // Size/type:
55 #define LONG 0x00001        // l: long or double
56 #define LONGDBL 0x00002     // L: long double
57 #define SHORT 0x00004       // h: short
58 #define SHORTSHORT 0x00008  // hh: 8 bit integer
59 #define LLONG 0x00010       // ll: long long (+ deprecated q: quad)
60 #define POINTER 0x00020     // p: void* (as hex)
61 #define SIZEINT 0x00040     // z: (signed) size_t
62 #define MAXINT 0x00080      // j: intmax_t
63 #define PTRINT 0x00100      // t: ptrdiff_t
64 #define NOSKIP 0x00200      // [ or c: do not skip blanks
65 // Modifiers:
66 #define SUPPRESS 0x00400  // *: suppress assignment
67 #define UNSIGNED 0x00800  // %[oupxX] conversions
68 #define ALLOCATE 0x01000  // m: allocate a char*
69 // Internal use during integer parsing:
70 #define SIGNOK 0x02000    // +/- is (still) legal
71 #define HAVESIGN 0x04000  // Sign detected
72 #define NDIGITS 0x08000   // No digits detected
73 #define PFXOK 0x10000     // "0x" prefix is (still) legal
74 #define PFBOK 0x20000     // "0b" prefix is (still) legal
75 #define NZDIGITS 0x40000  // No zero digits detected
76 
77 // Conversion types.
78 #define CT_CHAR 0    // %c conversion
79 #define CT_CCL 1     // %[...] conversion
80 #define CT_STRING 2  // %s conversion
81 #define CT_INT 3     // Integer: strtoimax/strtoumax
82 #define CT_FLOAT 4   // Float: strtod
83 
84 #define to_digit(c) static_cast<int>((c) - '0')
85 #define is_digit(c) (static_cast<unsigned>(to_digit(c)) <= 9)
86 
87 // Append a digit to a value and check for overflow.
88 #define APPEND_DIGIT(val, dig)               \
89   do {                                       \
90     if ((val) > INT_MAX / 10)                \
91       errno = ENOMEM;                        \
92     else {                                   \
93       (val) *= 10;                           \
94       if ((val) > INT_MAX - to_digit((dig))) \
95         errno = ENOMEM;                      \
96       else                                   \
97         (val) += to_digit((dig));            \
98     }                                        \
99   } while (0)
100 
101 #pragma clang diagnostic push
102 #pragma clang diagnostic ignored "-Wunused-function"
103 // Trasnlate a fixed size integer argument for the %w/%wf format to a
104 // flag representation. Supported sizes are 8, 16, 32, and 64 so far.
105 // See details in bionic/libc/include/stdint.h
w_to_flag(int size,bool fast)106 static int w_to_flag(int size, bool fast) {
107   static constexpr int fast_size = sizeof(void*) == 8 ? LLONG : 0;
108   if (size == 8) return SHORTSHORT;
109   if (size == 16) return fast ? fast_size : SHORT;
110   if (size == 32) return fast ? fast_size : 0;
111   if (size == 64) return LLONG;
112   __fortify_fatal("%%w%s%d is unsupported", fast ? "f" : "", size);
113 }
114 
115 #pragma clang diagnostic pop
116