/* $OpenBSD: vfscanf.c,v 1.31 2014/03/19 05:17:01 guenther Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #include #include #include #define BUF 513 /* Maximum length of numeric string. */ // Flags used during conversion. // Size/type: #define LONG 0x00001 // l: long or double #define LONGDBL 0x00002 // L: long double #define SHORT 0x00004 // h: short #define SHORTSHORT 0x00008 // hh: 8 bit integer #define LLONG 0x00010 // ll: long long (+ deprecated q: quad) #define POINTER 0x00020 // p: void* (as hex) #define SIZEINT 0x00040 // z: (signed) size_t #define MAXINT 0x00080 // j: intmax_t #define PTRINT 0x00100 // t: ptrdiff_t #define NOSKIP 0x00200 // [ or c: do not skip blanks // Modifiers: #define SUPPRESS 0x00400 // *: suppress assignment #define UNSIGNED 0x00800 // %[oupxX] conversions #define ALLOCATE 0x01000 // m: allocate a char* // Internal use during integer parsing: #define SIGNOK 0x02000 // +/- is (still) legal #define HAVESIGN 0x04000 // Sign detected #define NDIGITS 0x08000 // No digits detected #define PFXOK 0x10000 // "0x" prefix is (still) legal #define PFBOK 0x20000 // "0b" prefix is (still) legal #define NZDIGITS 0x40000 // No zero digits detected // Conversion types. #define CT_CHAR 0 // %c conversion #define CT_CCL 1 // %[...] conversion #define CT_STRING 2 // %s conversion #define CT_INT 3 // Integer: strtoimax/strtoumax #define CT_FLOAT 4 // Float: strtod #define to_digit(c) static_cast((c) - '0') #define is_digit(c) (static_cast(to_digit(c)) <= 9) // Append a digit to a value and check for overflow. #define APPEND_DIGIT(val, dig) \ do { \ if ((val) > INT_MAX / 10) \ errno = ENOMEM; \ else { \ (val) *= 10; \ if ((val) > INT_MAX - to_digit((dig))) \ errno = ENOMEM; \ else \ (val) += to_digit((dig)); \ } \ } while (0) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" // Trasnlate a fixed size integer argument for the %w/%wf format to a // flag representation. Supported sizes are 8, 16, 32, and 64 so far. // See details in bionic/libc/include/stdint.h static int w_to_flag(int size, bool fast) { static constexpr int fast_size = sizeof(void*) == 8 ? LLONG : 0; if (size == 8) return SHORTSHORT; if (size == 16) return fast ? fast_size : SHORT; if (size == 32) return fast ? fast_size : 0; if (size == 64) return LLONG; __fortify_fatal("%%w%s%d is unsupported", fast ? "f" : "", size); } #pragma clang diagnostic pop