13d58139fSopenharmony_ci/* 23d58139fSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved. 33d58139fSopenharmony_ci * Licensed under Mulan PSL v2. 43d58139fSopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2. 53d58139fSopenharmony_ci * You may obtain a copy of Mulan PSL v2 at: 63d58139fSopenharmony_ci * http://license.coscl.org.cn/MulanPSL2 73d58139fSopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 83d58139fSopenharmony_ci * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 93d58139fSopenharmony_ci * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 103d58139fSopenharmony_ci * See the Mulan PSL v2 for more details. 113d58139fSopenharmony_ci * Description: Used by secureinput_a.c and secureinput_w.c to include. 123d58139fSopenharmony_ci * This file provides a template function for ANSI and UNICODE compiling by 133d58139fSopenharmony_ci * different type definition. The functions of SecInputS or 143d58139fSopenharmony_ci * SecInputSW provides internal implementation for scanf family API, such as sscanf_s, fscanf_s. 153d58139fSopenharmony_ci * Create: 2014-02-25 163d58139fSopenharmony_ci * Notes: The formatted input processing results of integers on different platforms are different. 173d58139fSopenharmony_ci */ 183d58139fSopenharmony_ci/* 193d58139fSopenharmony_ci * [Standardize-exceptions] Use unsafe function: Performance-sensitive 203d58139fSopenharmony_ci * [reason] Always used in the performance critical path, 213d58139fSopenharmony_ci * and sufficient input validation is performed before calling 223d58139fSopenharmony_ci */ 233d58139fSopenharmony_ci#ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 243d58139fSopenharmony_ci#define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 253d58139fSopenharmony_ci 263d58139fSopenharmony_ci#if SECUREC_IN_KERNEL 273d58139fSopenharmony_ci#if !defined(SECUREC_CTYPE_MACRO_ADAPT) 283d58139fSopenharmony_ci#include <linux/ctype.h> 293d58139fSopenharmony_ci#endif 303d58139fSopenharmony_ci#else 313d58139fSopenharmony_ci#if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT) 323d58139fSopenharmony_ci#include <ctype.h> 333d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 343d58139fSopenharmony_ci#include <wctype.h> /* For iswspace */ 353d58139fSopenharmony_ci#endif 363d58139fSopenharmony_ci#endif 373d58139fSopenharmony_ci#endif 383d58139fSopenharmony_ci 393d58139fSopenharmony_ci#ifndef EOF 403d58139fSopenharmony_ci#define EOF (-1) 413d58139fSopenharmony_ci#endif 423d58139fSopenharmony_ci 433d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_SHORT 0 443d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_INT 1 453d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_LONG 2 463d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_LONG_LONG 3 /* Also long double */ 473d58139fSopenharmony_ci 483d58139fSopenharmony_ci#define SECUREC_BUFFERED_BLOK_SIZE 1024U 493d58139fSopenharmony_ci 503d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy) 513d58139fSopenharmony_ci/* The name is the same as system macro. */ 523d58139fSopenharmony_ci#define __va_copy(dest, src) do { \ 533d58139fSopenharmony_ci size_t destSize_ = (size_t)sizeof(dest); \ 543d58139fSopenharmony_ci size_t srcSize_ = (size_t)sizeof(src); \ 553d58139fSopenharmony_ci if (destSize_ != srcSize_) { \ 563d58139fSopenharmony_ci SECUREC_MEMCPY_WARP_OPT((dest), (src), sizeof(va_list)); \ 573d58139fSopenharmony_ci } else { \ 583d58139fSopenharmony_ci SECUREC_MEMCPY_WARP_OPT(&(dest), &(src), sizeof(va_list)); \ 593d58139fSopenharmony_ci } \ 603d58139fSopenharmony_ci} SECUREC_WHILE_ZERO 613d58139fSopenharmony_ci#endif 623d58139fSopenharmony_ci 633d58139fSopenharmony_ci#define SECUREC_MULTI_BYTE_MAX_LEN 6 643d58139fSopenharmony_ci 653d58139fSopenharmony_ci/* Compatibility macro name cannot be modifie */ 663d58139fSopenharmony_ci#ifndef UNALIGNED 673d58139fSopenharmony_ci#if !(defined(_M_IA64)) && !(defined(_M_AMD64)) 683d58139fSopenharmony_ci#define UNALIGNED 693d58139fSopenharmony_ci#else 703d58139fSopenharmony_ci#define UNALIGNED __unaligned 713d58139fSopenharmony_ci#endif 723d58139fSopenharmony_ci#endif 733d58139fSopenharmony_ci 743d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 753d58139fSopenharmony_ci/* Max 64bit value is 0xffffffffffffffff */ 763d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE 18446744073709551615ULL 773d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE_DIV_TEN 1844674407370955161ULL 783d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL 793d58139fSopenharmony_ci#define SECUREC_MIN_64BITS_NEG_VALUE 9223372036854775808ULL 803d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_POS_VALUE 9223372036854775807ULL 813d58139fSopenharmony_ci#define SECUREC_MIN_32BITS_NEG_VALUE 2147483648UL 823d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_POS_VALUE 2147483647UL 833d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE 4294967295UL 843d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE_INC 4294967296UL 853d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE_DIV_TEN 429496729UL 863d58139fSopenharmony_ci#define SECUREC_LONG_BIT_NUM ((unsigned int)(sizeof(long) << 3U)) 873d58139fSopenharmony_ci/* Use ULL to clean up cl6x compilation alerts */ 883d58139fSopenharmony_ci#define SECUREC_MAX_LONG_POS_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1) 893d58139fSopenharmony_ci#define SECUREC_MIN_LONG_NEG_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1))) 903d58139fSopenharmony_ci 913d58139fSopenharmony_ci/* Covert to long long to clean up cl6x compilation alerts */ 923d58139fSopenharmony_ci#define SECUREC_LONG_HEX_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0) 933d58139fSopenharmony_ci#define SECUREC_LONG_OCTAL_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0) 943d58139fSopenharmony_ci 953d58139fSopenharmony_ci#define SECUREC_QWORD_HEX_BEYOND_MAX(number) (((number) >> (64U - 4U)) > 0) 963d58139fSopenharmony_ci#define SECUREC_QWORD_OCTAL_BEYOND_MAX(number) (((number) >> (64U - 3U)) > 0) 973d58139fSopenharmony_ci 983d58139fSopenharmony_ci#define SECUREC_LP64_BIT_WIDTH 64 993d58139fSopenharmony_ci#define SECUREC_LP32_BIT_WIDTH 32 1003d58139fSopenharmony_ci 1013d58139fSopenharmony_ci#define SECUREC_CONVERT_IS_SIGNED(conv) ((conv) == 'd' || (conv) == 'i') 1023d58139fSopenharmony_ci#endif 1033d58139fSopenharmony_ci 1043d58139fSopenharmony_ci#define SECUREC_BRACE '{' /* [ to { */ 1053d58139fSopenharmony_ci#define SECUREC_FILED_WIDTH_ENOUGH(spec) ((spec)->widthSet == 0 || (spec)->width > 0) 1063d58139fSopenharmony_ci#define SECUREC_FILED_WIDTH_DEC(spec) do { \ 1073d58139fSopenharmony_ci if ((spec)->widthSet != 0) { \ 1083d58139fSopenharmony_ci --(spec)->width; \ 1093d58139fSopenharmony_ci } \ 1103d58139fSopenharmony_ci} SECUREC_WHILE_ZERO 1113d58139fSopenharmony_ci 1123d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 1133d58139fSopenharmony_ci/* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */ 1143d58139fSopenharmony_ci#define SECUREC_BRACKET_TABLE_SIZE 8192 1153d58139fSopenharmony_ci#define SECUREC_EOF WEOF 1163d58139fSopenharmony_ci#define SECUREC_MB_LEN 16 /* Max. # bytes in multibyte char ,see MB_LEN_MAX */ 1173d58139fSopenharmony_ci#else 1183d58139fSopenharmony_ci/* Bits for all char, size is 256/8 */ 1193d58139fSopenharmony_ci#define SECUREC_BRACKET_TABLE_SIZE 32 1203d58139fSopenharmony_ci#define SECUREC_EOF EOF 1213d58139fSopenharmony_ci#endif 1223d58139fSopenharmony_ci 1233d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART 1243d58139fSopenharmony_ci#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \ 1253d58139fSopenharmony_ci ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \ 1263d58139fSopenharmony_ci ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN)) 1273d58139fSopenharmony_ci#else 1283d58139fSopenharmony_ci#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || (spec).arrayWidth > SECUREC_STRING_MAX_LEN) 1293d58139fSopenharmony_ci#endif 1303d58139fSopenharmony_ci 1313d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 1323d58139fSopenharmony_ci/* Use 0xffffffffUL mask to pass integer as array length */ 1333d58139fSopenharmony_ci#define SECUREC_GET_ARRAYWIDTH(argList) (((size_t)va_arg((argList), size_t)) & 0xffffffffUL) 1343d58139fSopenharmony_ci#else /* !SECUREC_ON_64BITS */ 1353d58139fSopenharmony_ci#define SECUREC_GET_ARRAYWIDTH(argList) ((size_t)va_arg((argList), size_t)) 1363d58139fSopenharmony_ci#endif 1373d58139fSopenharmony_ci 1383d58139fSopenharmony_citypedef struct { 1393d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 1403d58139fSopenharmony_ci unsigned char *table; /* Default NULL */ 1413d58139fSopenharmony_ci#else 1423d58139fSopenharmony_ci unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */ 1433d58139fSopenharmony_ci#endif 1443d58139fSopenharmony_ci unsigned char mask; /* Default 0 */ 1453d58139fSopenharmony_ci} SecBracketTable; 1463d58139fSopenharmony_ci 1473d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 1483d58139fSopenharmony_ci#define SECUREC_INIT_BRACKET_TABLE { NULL, 0 } 1493d58139fSopenharmony_ci#else 1503d58139fSopenharmony_ci#define SECUREC_INIT_BRACKET_TABLE { {0}, 0 } 1513d58139fSopenharmony_ci#endif 1523d58139fSopenharmony_ci 1533d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT 1543d58139fSopenharmony_citypedef struct { 1553d58139fSopenharmony_ci size_t floatStrTotalLen; /* Initialization must be length of buffer in charater */ 1563d58139fSopenharmony_ci size_t floatStrUsedLen; /* Store float string len */ 1573d58139fSopenharmony_ci SecChar *floatStr; /* Initialization must point to buffer */ 1583d58139fSopenharmony_ci SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */ 1593d58139fSopenharmony_ci SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1]; 1603d58139fSopenharmony_ci} SecFloatSpec; 1613d58139fSopenharmony_ci#endif 1623d58139fSopenharmony_ci 1633d58139fSopenharmony_ci#define SECUREC_NUMBER_STATE_DEFAULT 0U 1643d58139fSopenharmony_ci#define SECUREC_NUMBER_STATE_STARTED 1U 1653d58139fSopenharmony_ci 1663d58139fSopenharmony_citypedef struct { 1673d58139fSopenharmony_ci SecInt ch; /* Char read from input */ 1683d58139fSopenharmony_ci int charCount; /* Number of characters processed */ 1693d58139fSopenharmony_ci void *argPtr; /* Variable parameter pointer, point to the end of the string */ 1703d58139fSopenharmony_ci size_t arrayWidth; /* Length of pointer Variable parameter, in charaters */ 1713d58139fSopenharmony_ci SecUnsignedInt64 number64; /* Store input number64 value */ 1723d58139fSopenharmony_ci unsigned long number; /* Store input number32 value */ 1733d58139fSopenharmony_ci int numberWidth; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ 1743d58139fSopenharmony_ci int numberArgType; /* 1 for 64-bit integer, 0 otherwise. use it as decode function index */ 1753d58139fSopenharmony_ci unsigned int negative; /* 0 is positive */ 1763d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1773d58139fSopenharmony_ci unsigned int beyondMax; /* Non-zero means beyond */ 1783d58139fSopenharmony_ci#endif 1793d58139fSopenharmony_ci unsigned int numberState; /* Identifies whether to start processing numbers, 1 is can input number */ 1803d58139fSopenharmony_ci int width; /* Width number in format */ 1813d58139fSopenharmony_ci int widthSet; /* 0 is not set width in format */ 1823d58139fSopenharmony_ci int convChr; /* Lowercase format conversion characters */ 1833d58139fSopenharmony_ci int oriConvChr; /* Store original format conversion, convChr may change when parsing integers */ 1843d58139fSopenharmony_ci signed char isWCharOrLong; /* -1/0 not wchar or long, 1 for wchar or long */ 1853d58139fSopenharmony_ci unsigned char suppress; /* 0 is not have %* in format */ 1863d58139fSopenharmony_ci} SecScanSpec; 1873d58139fSopenharmony_ci 1883d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 1893d58139fSopenharmony_ci#define SECUREC_GETC fgetwc 1903d58139fSopenharmony_ci#define SECUREC_UN_GETC ungetwc 1913d58139fSopenharmony_ci/* Only supports wide characters with a maximum length of two bytes in format string */ 1923d58139fSopenharmony_ci#define SECUREC_BRACKET_CHAR_MASK 0xffffU 1933d58139fSopenharmony_ci#else 1943d58139fSopenharmony_ci#define SECUREC_GETC fgetc 1953d58139fSopenharmony_ci#define SECUREC_UN_GETC ungetc 1963d58139fSopenharmony_ci#define SECUREC_BRACKET_CHAR_MASK 0xffU 1973d58139fSopenharmony_ci#endif 1983d58139fSopenharmony_ci 1993d58139fSopenharmony_ci#define SECUREC_CHAR_SIZE ((unsigned int)(sizeof(SecChar))) 2003d58139fSopenharmony_ci/* To avoid 648, mask high bit: 0x00ffffff 0x0000ffff or 0x00000000 */ 2013d58139fSopenharmony_ci#define SECUREC_CHAR_MASK_HIGH (((((((((unsigned int)(-1) >> SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 2023d58139fSopenharmony_ci SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 2033d58139fSopenharmony_ci SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 2043d58139fSopenharmony_ci SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) 2053d58139fSopenharmony_ci 2063d58139fSopenharmony_ci/* For char is 0xff, wcahr_t is 0xffff or 0xffffffff. */ 2073d58139fSopenharmony_ci#define SECUREC_CHAR_MASK (~((((((((((unsigned int)(-1) & SECUREC_CHAR_MASK_HIGH) << \ 2083d58139fSopenharmony_ci SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 2093d58139fSopenharmony_ci SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 2103d58139fSopenharmony_ci SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 2113d58139fSopenharmony_ci SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE)) 2123d58139fSopenharmony_ci 2133d58139fSopenharmony_ci/* According wchar_t has multiple bytes, so use sizeof */ 2143d58139fSopenharmony_ci#define SECUREC_GET_CHAR(stream, outCh) do { \ 2153d58139fSopenharmony_ci if ((stream)->count >= sizeof(SecChar)) { \ 2163d58139fSopenharmony_ci *(outCh) = (SecInt)(SECUREC_CHAR_MASK & \ 2173d58139fSopenharmony_ci (unsigned int)(int)(*((const SecChar *)(const void *)(stream)->cur))); \ 2183d58139fSopenharmony_ci (stream)->cur += sizeof(SecChar); \ 2193d58139fSopenharmony_ci (stream)->count -= sizeof(SecChar); \ 2203d58139fSopenharmony_ci } else { \ 2213d58139fSopenharmony_ci *(outCh) = SECUREC_EOF; \ 2223d58139fSopenharmony_ci } \ 2233d58139fSopenharmony_ci} SECUREC_WHILE_ZERO 2243d58139fSopenharmony_ci 2253d58139fSopenharmony_ci#define SECUREC_UN_GET_CHAR(stream) do { \ 2263d58139fSopenharmony_ci if ((stream)->cur > (stream)->base) { \ 2273d58139fSopenharmony_ci (stream)->cur -= sizeof(SecChar); \ 2283d58139fSopenharmony_ci (stream)->count += sizeof(SecChar); \ 2293d58139fSopenharmony_ci } \ 2303d58139fSopenharmony_ci} SECUREC_WHILE_ZERO 2313d58139fSopenharmony_ci 2323d58139fSopenharmony_ci/* Convert wchar_t to int and then to unsigned int to keep data clearing warning */ 2333d58139fSopenharmony_ci#define SECUREC_TO_LOWERCASE(chr) ((int)((unsigned int)(int)(chr) | (unsigned int)('a' - 'A'))) 2343d58139fSopenharmony_ci 2353d58139fSopenharmony_ci/* Record a flag for each bit */ 2363d58139fSopenharmony_ci#define SECUREC_BRACKET_INDEX(x) ((unsigned int)(x) >> 3U) 2373d58139fSopenharmony_ci#define SECUREC_BRACKET_VALUE(x) ((unsigned char)(1U << ((unsigned int)(x) & 7U))) 2383d58139fSopenharmony_ci#if SECUREC_IN_KERNEL 2393d58139fSopenharmony_ci#define SECUREC_CONVERT_IS_UNSIGNED(conv) ((conv) == 'x' || (conv) == 'o' || (conv) == 'u') 2403d58139fSopenharmony_ci#endif 2413d58139fSopenharmony_ci 2423d58139fSopenharmony_ci/* 2433d58139fSopenharmony_ci * Set char in %[xxx] into table, only supports wide characters with a maximum length of two bytes 2443d58139fSopenharmony_ci */ 2453d58139fSopenharmony_ciSECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch) 2463d58139fSopenharmony_ci{ 2473d58139fSopenharmony_ci unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 2483d58139fSopenharmony_ci unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 2493d58139fSopenharmony_ci /* Do not use |= optimize this code, it will cause compiling warning */ 2503d58139fSopenharmony_ci table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue); 2513d58139fSopenharmony_ci} 2523d58139fSopenharmony_ci 2533d58139fSopenharmony_ciSECUREC_INLINE void SecBracketSetBitRange(unsigned char *table, SecUnsignedChar startCh, SecUnsignedChar endCh) 2543d58139fSopenharmony_ci{ 2553d58139fSopenharmony_ci SecUnsignedChar expCh; 2563d58139fSopenharmony_ci /* %[a-z] %[a-a] Format %[a-\xff] end is 0xFF, condition (expCh <= endChar) cause dead loop */ 2573d58139fSopenharmony_ci for (expCh = startCh; expCh < endCh; ++expCh) { 2583d58139fSopenharmony_ci SecBracketSetBit(table, expCh); 2593d58139fSopenharmony_ci } 2603d58139fSopenharmony_ci SecBracketSetBit(table, endCh); 2613d58139fSopenharmony_ci} 2623d58139fSopenharmony_ci/* 2633d58139fSopenharmony_ci * Determine whether the expression can be satisfied 2643d58139fSopenharmony_ci */ 2653d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable) 2663d58139fSopenharmony_ci{ 2673d58139fSopenharmony_ci unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 2683d58139fSopenharmony_ci unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 2693d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 2703d58139fSopenharmony_ci if (((unsigned int)(int)ch & (~(SECUREC_BRACKET_CHAR_MASK))) != 0) { 2713d58139fSopenharmony_ci /* The value of the wide character exceeds the size of two bytes */ 2723d58139fSopenharmony_ci return 0; 2733d58139fSopenharmony_ci } 2743d58139fSopenharmony_ci return (int)(convChr == SECUREC_BRACE && 2753d58139fSopenharmony_ci (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0); 2763d58139fSopenharmony_ci#else 2773d58139fSopenharmony_ci return (int)(convChr == SECUREC_BRACE && 2783d58139fSopenharmony_ci (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0); 2793d58139fSopenharmony_ci#endif 2803d58139fSopenharmony_ci} 2813d58139fSopenharmony_ci 2823d58139fSopenharmony_ci/* 2833d58139fSopenharmony_ci * String input ends when blank character is encountered 2843d58139fSopenharmony_ci */ 2853d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputString(int convChr, SecInt ch) 2863d58139fSopenharmony_ci{ 2873d58139fSopenharmony_ci return (int)(convChr == 's' && 2883d58139fSopenharmony_ci (!(ch >= SECUREC_CHAR('\t') && ch <= SECUREC_CHAR('\r')) && ch != SECUREC_CHAR(' '))); 2893d58139fSopenharmony_ci} 2903d58139fSopenharmony_ci 2913d58139fSopenharmony_ci/* 2923d58139fSopenharmony_ci * Can input a character when format is %c 2933d58139fSopenharmony_ci */ 2943d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputCharacter(int convChr) 2953d58139fSopenharmony_ci{ 2963d58139fSopenharmony_ci return (int)(convChr == 'c'); 2973d58139fSopenharmony_ci} 2983d58139fSopenharmony_ci 2993d58139fSopenharmony_ci/* 3003d58139fSopenharmony_ci * Determine if it is a 64-bit pointer function 3013d58139fSopenharmony_ci * Return 0 is not ,1 is 64bit pointer 3023d58139fSopenharmony_ci */ 3033d58139fSopenharmony_ciSECUREC_INLINE int SecNumberArgType(size_t sizeOfVoidStar) 3043d58139fSopenharmony_ci{ 3053d58139fSopenharmony_ci /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */ 3063d58139fSopenharmony_ci /* To clear e778 */ 3073d58139fSopenharmony_ci if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) { 3083d58139fSopenharmony_ci return 1; 3093d58139fSopenharmony_ci } 3103d58139fSopenharmony_ci return 0; 3113d58139fSopenharmony_ci} 3123d58139fSopenharmony_ciSECUREC_INLINE int SecIsDigit(SecInt ch); 3133d58139fSopenharmony_ciSECUREC_INLINE int SecIsXdigit(SecInt ch); 3143d58139fSopenharmony_ciSECUREC_INLINE int SecIsSpace(SecInt ch); 3153d58139fSopenharmony_ciSECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter); 3163d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter); 3173d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter); 3183d58139fSopenharmony_ci 3193d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT 3203d58139fSopenharmony_ci 3213d58139fSopenharmony_ci/* 3223d58139fSopenharmony_ci * Convert a floating point string to a floating point number 3233d58139fSopenharmony_ci */ 3243d58139fSopenharmony_ciSECUREC_INLINE int SecAssignNarrowFloat(const char *floatStr, const SecScanSpec *spec) 3253d58139fSopenharmony_ci{ 3263d58139fSopenharmony_ci char *endPtr = NULL; 3273d58139fSopenharmony_ci double d; 3283d58139fSopenharmony_ci#if SECUREC_SUPPORT_STRTOLD 3293d58139fSopenharmony_ci if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) { 3303d58139fSopenharmony_ci long double d2 = strtold(floatStr, &endPtr); 3313d58139fSopenharmony_ci if (endPtr == floatStr) { 3323d58139fSopenharmony_ci return -1; 3333d58139fSopenharmony_ci } 3343d58139fSopenharmony_ci *(long double UNALIGNED *)(spec->argPtr) = d2; 3353d58139fSopenharmony_ci return 0; 3363d58139fSopenharmony_ci } 3373d58139fSopenharmony_ci#endif 3383d58139fSopenharmony_ci d = strtod(floatStr, &endPtr); 3393d58139fSopenharmony_ci /* cannot detect if endPtr points to the end of floatStr,because strtod handles only two characters for 1.E */ 3403d58139fSopenharmony_ci if (endPtr == floatStr) { 3413d58139fSopenharmony_ci return -1; 3423d58139fSopenharmony_ci } 3433d58139fSopenharmony_ci if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) { 3443d58139fSopenharmony_ci *(double UNALIGNED *)(spec->argPtr) = (double)d; 3453d58139fSopenharmony_ci } else { 3463d58139fSopenharmony_ci *(float UNALIGNED *)(spec->argPtr) = (float)d; 3473d58139fSopenharmony_ci } 3483d58139fSopenharmony_ci return 0; 3493d58139fSopenharmony_ci} 3503d58139fSopenharmony_ci 3513d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 3523d58139fSopenharmony_ci/* 3533d58139fSopenharmony_ci * Convert a floating point wchar string to a floating point number 3543d58139fSopenharmony_ci * Success ret 0 3553d58139fSopenharmony_ci */ 3563d58139fSopenharmony_ciSECUREC_INLINE int SecAssignWideFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec) 3573d58139fSopenharmony_ci{ 3583d58139fSopenharmony_ci int retVal; 3593d58139fSopenharmony_ci /* Convert float string */ 3603d58139fSopenharmony_ci size_t mbsLen; 3613d58139fSopenharmony_ci size_t tempFloatStrLen = (size_t)(floatSpec->floatStrUsedLen + 1) * sizeof(wchar_t); 3623d58139fSopenharmony_ci char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen); 3633d58139fSopenharmony_ci if (tempFloatStr == NULL) { 3643d58139fSopenharmony_ci return -1; 3653d58139fSopenharmony_ci } 3663d58139fSopenharmony_ci tempFloatStr[0] = '\0'; 3673d58139fSopenharmony_ci SECUREC_MASK_MSVC_CRT_WARNING 3683d58139fSopenharmony_ci mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1); 3693d58139fSopenharmony_ci SECUREC_END_MASK_MSVC_CRT_WARNING 3703d58139fSopenharmony_ci /* This condition must satisfy mbsLen is not -1 */ 3713d58139fSopenharmony_ci if (mbsLen >= tempFloatStrLen) { 3723d58139fSopenharmony_ci SECUREC_FREE(tempFloatStr); 3733d58139fSopenharmony_ci return -1; 3743d58139fSopenharmony_ci } 3753d58139fSopenharmony_ci tempFloatStr[mbsLen] = '\0'; 3763d58139fSopenharmony_ci retVal = SecAssignNarrowFloat(tempFloatStr, spec); 3773d58139fSopenharmony_ci SECUREC_FREE(tempFloatStr); 3783d58139fSopenharmony_ci return retVal; 3793d58139fSopenharmony_ci} 3803d58139fSopenharmony_ci#endif 3813d58139fSopenharmony_ci 3823d58139fSopenharmony_ciSECUREC_INLINE int SecAssignFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec) 3833d58139fSopenharmony_ci{ 3843d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 3853d58139fSopenharmony_ci return SecAssignWideFloat(floatSpec, spec); 3863d58139fSopenharmony_ci#else 3873d58139fSopenharmony_ci return SecAssignNarrowFloat(floatSpec->floatStr, spec); 3883d58139fSopenharmony_ci#endif 3893d58139fSopenharmony_ci} 3903d58139fSopenharmony_ci 3913d58139fSopenharmony_ci/* 3923d58139fSopenharmony_ci * Init SecFloatSpec before parse format 3933d58139fSopenharmony_ci */ 3943d58139fSopenharmony_ciSECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec) 3953d58139fSopenharmony_ci{ 3963d58139fSopenharmony_ci floatSpec->floatStr = floatSpec->buffer; 3973d58139fSopenharmony_ci floatSpec->allocatedFloatStr = NULL; 3983d58139fSopenharmony_ci floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]); 3993d58139fSopenharmony_ci floatSpec->floatStrUsedLen = 0; 4003d58139fSopenharmony_ci} 4013d58139fSopenharmony_ci 4023d58139fSopenharmony_ciSECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount) 4033d58139fSopenharmony_ci{ 4043d58139fSopenharmony_ci /* 2014.3.6 add, clear the stack data */ 4053d58139fSopenharmony_ci if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) { 4063d58139fSopenharmony_ci *doneCount = 0; /* This code just to meet the coding requirements */ 4073d58139fSopenharmony_ci } 4083d58139fSopenharmony_ci /* The pFloatStr can be alloced in SecExtendFloatLen function, clear and free it */ 4093d58139fSopenharmony_ci if (floatSpec->allocatedFloatStr != NULL) { 4103d58139fSopenharmony_ci size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar); 4113d58139fSopenharmony_ci if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) { 4123d58139fSopenharmony_ci *doneCount = 0; /* This code just to meet the coding requirements */ 4133d58139fSopenharmony_ci } 4143d58139fSopenharmony_ci SECUREC_FREE(floatSpec->allocatedFloatStr); 4153d58139fSopenharmony_ci floatSpec->allocatedFloatStr = NULL; 4163d58139fSopenharmony_ci floatSpec->floatStr = NULL; 4173d58139fSopenharmony_ci } 4183d58139fSopenharmony_ci} 4193d58139fSopenharmony_ci 4203d58139fSopenharmony_ci/* 4213d58139fSopenharmony_ci * Splice floating point string 4223d58139fSopenharmony_ci * Return 0 OK 4233d58139fSopenharmony_ci */ 4243d58139fSopenharmony_ciSECUREC_INLINE int SecExtendFloatLen(SecFloatSpec *floatSpec) 4253d58139fSopenharmony_ci{ 4263d58139fSopenharmony_ci if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) { 4273d58139fSopenharmony_ci /* Buffer size is len x sizeof(SecChar) */ 4283d58139fSopenharmony_ci size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar); 4293d58139fSopenharmony_ci /* Add one character to clear tool warning */ 4303d58139fSopenharmony_ci size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */ 4313d58139fSopenharmony_ci 4323d58139fSopenharmony_ci /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */ 4333d58139fSopenharmony_ci if (nextSize <= (size_t)SECUREC_MAX_WIDTH_LEN) { 4343d58139fSopenharmony_ci void *nextBuffer = (void *)SECUREC_MALLOC(nextSize); 4353d58139fSopenharmony_ci if (nextBuffer == NULL) { 4363d58139fSopenharmony_ci return -1; 4373d58139fSopenharmony_ci } 4383d58139fSopenharmony_ci if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) { 4393d58139fSopenharmony_ci SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ 4403d58139fSopenharmony_ci return -1; 4413d58139fSopenharmony_ci } 4423d58139fSopenharmony_ci /* Clear old buffer memory */ 4433d58139fSopenharmony_ci if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) { 4443d58139fSopenharmony_ci SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ 4453d58139fSopenharmony_ci return -1; 4463d58139fSopenharmony_ci } 4473d58139fSopenharmony_ci /* Free old allocated buffer */ 4483d58139fSopenharmony_ci if (floatSpec->allocatedFloatStr != NULL) { 4493d58139fSopenharmony_ci SECUREC_FREE(floatSpec->allocatedFloatStr); 4503d58139fSopenharmony_ci } 4513d58139fSopenharmony_ci floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer); /* Use to clear free on stack warning */ 4523d58139fSopenharmony_ci floatSpec->floatStr = (SecChar *)(nextBuffer); 4533d58139fSopenharmony_ci floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */ 4543d58139fSopenharmony_ci return 0; 4553d58139fSopenharmony_ci } 4563d58139fSopenharmony_ci return -1; /* Next size is beyond max */ 4573d58139fSopenharmony_ci } 4583d58139fSopenharmony_ci return 0; 4593d58139fSopenharmony_ci} 4603d58139fSopenharmony_ci 4613d58139fSopenharmony_ci/* Do not use localeconv()->decimal_pointif only support '.' */ 4623d58139fSopenharmony_ciSECUREC_INLINE int SecIsFloatDecimal(SecChar ch) 4633d58139fSopenharmony_ci{ 4643d58139fSopenharmony_ci return (int)(ch == SECUREC_CHAR('.')); 4653d58139fSopenharmony_ci} 4663d58139fSopenharmony_ci 4673d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatSign(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 4683d58139fSopenharmony_ci{ 4693d58139fSopenharmony_ci if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) { 4703d58139fSopenharmony_ci return 0; 4713d58139fSopenharmony_ci } 4723d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 4733d58139fSopenharmony_ci if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { 4743d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Make sure the count after un get char is correct */ 4753d58139fSopenharmony_ci if (spec->ch == SECUREC_CHAR('-')) { 4763d58139fSopenharmony_ci floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('-'); 4773d58139fSopenharmony_ci ++floatSpec->floatStrUsedLen; 4783d58139fSopenharmony_ci if (SecExtendFloatLen(floatSpec) != 0) { 4793d58139fSopenharmony_ci return -1; 4803d58139fSopenharmony_ci } 4813d58139fSopenharmony_ci } 4823d58139fSopenharmony_ci } else { 4833d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 4843d58139fSopenharmony_ci } 4853d58139fSopenharmony_ci return 0; 4863d58139fSopenharmony_ci} 4873d58139fSopenharmony_ci 4883d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatDigit(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 4893d58139fSopenharmony_ci{ 4903d58139fSopenharmony_ci /* Now get integral part */ 4913d58139fSopenharmony_ci while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 4923d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 4933d58139fSopenharmony_ci if (SecIsDigit(spec->ch) == 0) { 4943d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 4953d58139fSopenharmony_ci return 0; 4963d58139fSopenharmony_ci } 4973d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 4983d58139fSopenharmony_ci spec->numberState = SECUREC_NUMBER_STATE_STARTED; 4993d58139fSopenharmony_ci floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch; 5003d58139fSopenharmony_ci ++floatSpec->floatStrUsedLen; 5013d58139fSopenharmony_ci if (SecExtendFloatLen(floatSpec) != 0) { 5023d58139fSopenharmony_ci return -1; 5033d58139fSopenharmony_ci } 5043d58139fSopenharmony_ci } 5053d58139fSopenharmony_ci return 0; 5063d58139fSopenharmony_ci} 5073d58139fSopenharmony_ci 5083d58139fSopenharmony_ci/* 5093d58139fSopenharmony_ci* Scan value of exponent. 5103d58139fSopenharmony_ci* Return 0 OK 5113d58139fSopenharmony_ci*/ 5123d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 5133d58139fSopenharmony_ci{ 5143d58139fSopenharmony_ci if (SecInputFloatSign(stream, spec, floatSpec) == -1) { 5153d58139fSopenharmony_ci return -1; 5163d58139fSopenharmony_ci } 5173d58139fSopenharmony_ci if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 5183d58139fSopenharmony_ci return -1; 5193d58139fSopenharmony_ci } 5203d58139fSopenharmony_ci return 0; 5213d58139fSopenharmony_ci} 5223d58139fSopenharmony_ci 5233d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatFractional(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 5243d58139fSopenharmony_ci{ 5253d58139fSopenharmony_ci if (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 5263d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 5273d58139fSopenharmony_ci if (SecIsFloatDecimal((SecChar)spec->ch) == 0) { 5283d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 5293d58139fSopenharmony_ci return 0; 5303d58139fSopenharmony_ci } 5313d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 5323d58139fSopenharmony_ci /* Now check for decimal */ 5333d58139fSopenharmony_ci floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch; 5343d58139fSopenharmony_ci ++floatSpec->floatStrUsedLen; 5353d58139fSopenharmony_ci if (SecExtendFloatLen(floatSpec) != 0) { 5363d58139fSopenharmony_ci return -1; 5373d58139fSopenharmony_ci } 5383d58139fSopenharmony_ci if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 5393d58139fSopenharmony_ci return -1; 5403d58139fSopenharmony_ci } 5413d58139fSopenharmony_ci } 5423d58139fSopenharmony_ci return 0; 5433d58139fSopenharmony_ci} 5443d58139fSopenharmony_ci 5453d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatExponent(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 5463d58139fSopenharmony_ci{ 5473d58139fSopenharmony_ci /* Now get exponent part */ 5483d58139fSopenharmony_ci if (spec->numberState == SECUREC_NUMBER_STATE_STARTED && SECUREC_FILED_WIDTH_ENOUGH(spec)) { 5493d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 5503d58139fSopenharmony_ci if (spec->ch != SECUREC_CHAR('e') && spec->ch != SECUREC_CHAR('E')) { 5513d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 5523d58139fSopenharmony_ci return 0; 5533d58139fSopenharmony_ci } 5543d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 5553d58139fSopenharmony_ci floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('e'); 5563d58139fSopenharmony_ci ++floatSpec->floatStrUsedLen; 5573d58139fSopenharmony_ci if (SecExtendFloatLen(floatSpec) != 0) { 5583d58139fSopenharmony_ci return -1; 5593d58139fSopenharmony_ci } 5603d58139fSopenharmony_ci if (SecInputFloatE(stream, spec, floatSpec) != 0) { 5613d58139fSopenharmony_ci return -1; 5623d58139fSopenharmony_ci } 5633d58139fSopenharmony_ci } 5643d58139fSopenharmony_ci return 0; 5653d58139fSopenharmony_ci} 5663d58139fSopenharmony_ci 5673d58139fSopenharmony_ci/* 5683d58139fSopenharmony_ci* Scan %f. 5693d58139fSopenharmony_ci* Return 0 OK 5703d58139fSopenharmony_ci*/ 5713d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 5723d58139fSopenharmony_ci{ 5733d58139fSopenharmony_ci floatSpec->floatStrUsedLen = 0; 5743d58139fSopenharmony_ci 5753d58139fSopenharmony_ci /* The following code sequence is strict */ 5763d58139fSopenharmony_ci if (SecInputFloatSign(stream, spec, floatSpec) != 0) { 5773d58139fSopenharmony_ci return -1; 5783d58139fSopenharmony_ci } 5793d58139fSopenharmony_ci if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 5803d58139fSopenharmony_ci return -1; 5813d58139fSopenharmony_ci } 5823d58139fSopenharmony_ci if (SecInputFloatFractional(stream, spec, floatSpec) != 0) { 5833d58139fSopenharmony_ci return -1; 5843d58139fSopenharmony_ci } 5853d58139fSopenharmony_ci if (SecInputFloatExponent(stream, spec, floatSpec) != 0) { 5863d58139fSopenharmony_ci return -1; 5873d58139fSopenharmony_ci } 5883d58139fSopenharmony_ci 5893d58139fSopenharmony_ci /* Make sure have a string terminator, buffer is large enough */ 5903d58139fSopenharmony_ci floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0'); 5913d58139fSopenharmony_ci if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) { 5923d58139fSopenharmony_ci return 0; 5933d58139fSopenharmony_ci } 5943d58139fSopenharmony_ci return -1; 5953d58139fSopenharmony_ci} 5963d58139fSopenharmony_ci#endif 5973d58139fSopenharmony_ci 5983d58139fSopenharmony_ci#if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \ 5993d58139fSopenharmony_ci (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)) 6003d58139fSopenharmony_ci/* only multi-bytes string need isleadbyte() function */ 6013d58139fSopenharmony_ciSECUREC_INLINE int SecIsLeadByte(SecInt ch) 6023d58139fSopenharmony_ci{ 6033d58139fSopenharmony_ci unsigned int c = (unsigned int)ch; 6043d58139fSopenharmony_ci#if !(defined(_MSC_VER) || defined(_INC_WCTYPE)) 6053d58139fSopenharmony_ci return (int)(c & 0x80U); /* Use bitwise operation to check if the most significant bit is 1 */ 6063d58139fSopenharmony_ci#else 6073d58139fSopenharmony_ci return (int)isleadbyte((int)(c & 0xffU)); /* Use bitwise operations to limit character values to valid ranges */ 6083d58139fSopenharmony_ci#endif 6093d58139fSopenharmony_ci} 6103d58139fSopenharmony_ci#endif 6113d58139fSopenharmony_ci 6123d58139fSopenharmony_ci/* 6133d58139fSopenharmony_ci * Parsing whether it is a wide character 6143d58139fSopenharmony_ci */ 6153d58139fSopenharmony_ciSECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec) 6163d58139fSopenharmony_ci{ 6173d58139fSopenharmony_ci if (spec->isWCharOrLong != 0) { 6183d58139fSopenharmony_ci /* Wide character identifiers have been explicitly set by l or h flag */ 6193d58139fSopenharmony_ci return; 6203d58139fSopenharmony_ci } 6213d58139fSopenharmony_ci 6223d58139fSopenharmony_ci /* Set default flag */ 6233d58139fSopenharmony_ci#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) 6243d58139fSopenharmony_ci spec->isWCharOrLong = 1; /* On windows wide char version %c %s %[ is wide char */ 6253d58139fSopenharmony_ci#else 6263d58139fSopenharmony_ci spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */ 6273d58139fSopenharmony_ci#endif 6283d58139fSopenharmony_ci 6293d58139fSopenharmony_ci if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) { 6303d58139fSopenharmony_ci#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) 6313d58139fSopenharmony_ci spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */ 6323d58139fSopenharmony_ci#else 6333d58139fSopenharmony_ci spec->isWCharOrLong = 1; /* On linux all version %C %S is wide char */ 6343d58139fSopenharmony_ci#endif 6353d58139fSopenharmony_ci } 6363d58139fSopenharmony_ci 6373d58139fSopenharmony_ci return; 6383d58139fSopenharmony_ci} 6393d58139fSopenharmony_ci/* 6403d58139fSopenharmony_ci * Decode %l %ll 6413d58139fSopenharmony_ci */ 6423d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec) 6433d58139fSopenharmony_ci{ 6443d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 6453d58139fSopenharmony_ci if (*(fmt + 1) == SECUREC_CHAR('l')) { 6463d58139fSopenharmony_ci spec->numberArgType = 1; 6473d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 6483d58139fSopenharmony_ci ++fmt; 6493d58139fSopenharmony_ci } else { 6503d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG; 6513d58139fSopenharmony_ci#if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 6523d58139fSopenharmony_ci /* On window 64 system sizeof long is 32bit */ 6533d58139fSopenharmony_ci spec->numberArgType = 1; 6543d58139fSopenharmony_ci#endif 6553d58139fSopenharmony_ci spec->isWCharOrLong = 1; 6563d58139fSopenharmony_ci } 6573d58139fSopenharmony_ci *format = fmt; 6583d58139fSopenharmony_ci} 6593d58139fSopenharmony_ci 6603d58139fSopenharmony_ci/* 6613d58139fSopenharmony_ci * Decode %I %I43 %I64 %Id %Ii %Io ... 6623d58139fSopenharmony_ci * Set finishFlag to 1 finish Flag 6633d58139fSopenharmony_ci */ 6643d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) 6653d58139fSopenharmony_ci{ 6663d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 6673d58139fSopenharmony_ci if ((*(fmt + 1) == SECUREC_CHAR('6')) && 6683d58139fSopenharmony_ci (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */ 6693d58139fSopenharmony_ci spec->numberArgType = 1; 6703d58139fSopenharmony_ci *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */ 6713d58139fSopenharmony_ci } else if ((*(fmt + 1) == SECUREC_CHAR('3')) && 6723d58139fSopenharmony_ci (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */ 6733d58139fSopenharmony_ci *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */ 6743d58139fSopenharmony_ci } else if ((*(fmt + 1) == SECUREC_CHAR('d')) || 6753d58139fSopenharmony_ci (*(fmt + 1) == SECUREC_CHAR('i')) || 6763d58139fSopenharmony_ci (*(fmt + 1) == SECUREC_CHAR('o')) || 6773d58139fSopenharmony_ci (*(fmt + 1) == SECUREC_CHAR('x')) || 6783d58139fSopenharmony_ci (*(fmt + 1) == SECUREC_CHAR('X'))) { 6793d58139fSopenharmony_ci spec->numberArgType = SecNumberArgType(sizeof(void *)); 6803d58139fSopenharmony_ci } else { 6813d58139fSopenharmony_ci /* For %I */ 6823d58139fSopenharmony_ci spec->numberArgType = SecNumberArgType(sizeof(void *)); 6833d58139fSopenharmony_ci *finishFlag = 1; 6843d58139fSopenharmony_ci } 6853d58139fSopenharmony_ci} 6863d58139fSopenharmony_ci 6873d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec) 6883d58139fSopenharmony_ci{ 6893d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 6903d58139fSopenharmony_ci while (SecIsDigit((SecInt)(int)(*fmt)) != 0) { 6913d58139fSopenharmony_ci spec->widthSet = 1; 6923d58139fSopenharmony_ci if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) { 6933d58139fSopenharmony_ci return -1; 6943d58139fSopenharmony_ci } 6953d58139fSopenharmony_ci spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0')); 6963d58139fSopenharmony_ci ++fmt; 6973d58139fSopenharmony_ci } 6983d58139fSopenharmony_ci *format = fmt; 6993d58139fSopenharmony_ci return 0; 7003d58139fSopenharmony_ci} 7013d58139fSopenharmony_ci 7023d58139fSopenharmony_ci/* 7033d58139fSopenharmony_ci * Init default flags for each format. do not init ch this variable is context-dependent 7043d58139fSopenharmony_ci */ 7053d58139fSopenharmony_ciSECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec) 7063d58139fSopenharmony_ci{ 7073d58139fSopenharmony_ci /* The ch and charCount member variables cannot be initialized here */ 7083d58139fSopenharmony_ci spec->argPtr = NULL; 7093d58139fSopenharmony_ci spec->arrayWidth = 0; 7103d58139fSopenharmony_ci spec->number64 = 0; 7113d58139fSopenharmony_ci spec->number = 0; 7123d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_INT; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ 7133d58139fSopenharmony_ci spec->numberArgType = 0; /* 1 for 64-bit integer, 0 otherwise */ 7143d58139fSopenharmony_ci spec->width = 0; 7153d58139fSopenharmony_ci spec->widthSet = 0; 7163d58139fSopenharmony_ci spec->convChr = 0; 7173d58139fSopenharmony_ci spec->oriConvChr = 0; 7183d58139fSopenharmony_ci spec->isWCharOrLong = 0; 7193d58139fSopenharmony_ci spec->suppress = 0; 7203d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 7213d58139fSopenharmony_ci spec->beyondMax = 0; 7223d58139fSopenharmony_ci#endif 7233d58139fSopenharmony_ci spec->negative = 0; 7243d58139fSopenharmony_ci spec->numberState = SECUREC_NUMBER_STATE_DEFAULT; 7253d58139fSopenharmony_ci} 7263d58139fSopenharmony_ci 7273d58139fSopenharmony_ci/* 7283d58139fSopenharmony_ci * Decode qualifier %I %L %h ... 7293d58139fSopenharmony_ci * Set finishFlag to 1 finish Flag 7303d58139fSopenharmony_ci */ 7313d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) 7323d58139fSopenharmony_ci{ 7333d58139fSopenharmony_ci switch (**format) { 7343d58139fSopenharmony_ci case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 7353d58139fSopenharmony_ci case SECUREC_CHAR('N'): 7363d58139fSopenharmony_ci break; 7373d58139fSopenharmony_ci case SECUREC_CHAR('h'): 7383d58139fSopenharmony_ci --spec->numberWidth; /* The h for SHORT , hh for CHAR */ 7393d58139fSopenharmony_ci spec->isWCharOrLong = -1; 7403d58139fSopenharmony_ci break; 7413d58139fSopenharmony_ci#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 7423d58139fSopenharmony_ci case SECUREC_CHAR('j'): 7433d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* For intmax_t or uintmax_t */ 7443d58139fSopenharmony_ci spec->numberArgType = 1; 7453d58139fSopenharmony_ci break; 7463d58139fSopenharmony_ci case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */ 7473d58139fSopenharmony_ci#endif 7483d58139fSopenharmony_ci#if SECUREC_IN_KERNEL 7493d58139fSopenharmony_ci case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */ 7503d58139fSopenharmony_ci#endif 7513d58139fSopenharmony_ci case SECUREC_CHAR('z'): 7523d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 7533d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 7543d58139fSopenharmony_ci spec->numberArgType = 1; 7553d58139fSopenharmony_ci#else 7563d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG; 7573d58139fSopenharmony_ci#endif 7583d58139fSopenharmony_ci break; 7593d58139fSopenharmony_ci case SECUREC_CHAR('L'): /* For long double */ /* fall-through */ /* FALLTHRU */ 7603d58139fSopenharmony_ci case SECUREC_CHAR('q'): 7613d58139fSopenharmony_ci spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 7623d58139fSopenharmony_ci spec->numberArgType = 1; 7633d58139fSopenharmony_ci break; 7643d58139fSopenharmony_ci case SECUREC_CHAR('l'): 7653d58139fSopenharmony_ci SecDecodeScanQualifierL(format, spec); 7663d58139fSopenharmony_ci break; 7673d58139fSopenharmony_ci case SECUREC_CHAR('w'): 7683d58139fSopenharmony_ci spec->isWCharOrLong = 1; 7693d58139fSopenharmony_ci break; 7703d58139fSopenharmony_ci case SECUREC_CHAR('*'): 7713d58139fSopenharmony_ci spec->suppress = 1; 7723d58139fSopenharmony_ci break; 7733d58139fSopenharmony_ci case SECUREC_CHAR('I'): 7743d58139fSopenharmony_ci SecDecodeScanQualifierI(format, spec, finishFlag); 7753d58139fSopenharmony_ci break; 7763d58139fSopenharmony_ci default: 7773d58139fSopenharmony_ci *finishFlag = 1; 7783d58139fSopenharmony_ci break; 7793d58139fSopenharmony_ci } 7803d58139fSopenharmony_ci} 7813d58139fSopenharmony_ci/* 7823d58139fSopenharmony_ci * Decode width and qualifier in format 7833d58139fSopenharmony_ci */ 7843d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec) 7853d58139fSopenharmony_ci{ 7863d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 7873d58139fSopenharmony_ci int finishFlag = 0; 7883d58139fSopenharmony_ci 7893d58139fSopenharmony_ci do { 7903d58139fSopenharmony_ci ++fmt; /* First skip % , next seek fmt */ 7913d58139fSopenharmony_ci /* May %*6d , so put it inside the loop */ 7923d58139fSopenharmony_ci if (SecDecodeScanWidth(&fmt, spec) != 0) { 7933d58139fSopenharmony_ci return -1; 7943d58139fSopenharmony_ci } 7953d58139fSopenharmony_ci SecDecodeScanQualifier(&fmt, spec, &finishFlag); 7963d58139fSopenharmony_ci } while (finishFlag == 0); 7973d58139fSopenharmony_ci *format = fmt; 7983d58139fSopenharmony_ci return 0; 7993d58139fSopenharmony_ci} 8003d58139fSopenharmony_ci 8013d58139fSopenharmony_ci/* 8023d58139fSopenharmony_ci * Judging whether a zeroing buffer is needed according to different formats 8033d58139fSopenharmony_ci */ 8043d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr) 8053d58139fSopenharmony_ci{ 8063d58139fSopenharmony_ci const SecUnsignedChar *fmt = format; 8073d58139fSopenharmony_ci /* To lowercase */ 8083d58139fSopenharmony_ci int ch = SECUREC_TO_LOWERCASE(*fmt); 8093d58139fSopenharmony_ci if (!(ch == 'c' || ch == 's' || ch == SECUREC_BRACE)) { 8103d58139fSopenharmony_ci return -1; /* First argument is not a string type */ 8113d58139fSopenharmony_ci } 8123d58139fSopenharmony_ci if (ch == SECUREC_BRACE) { 8133d58139fSopenharmony_ci#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 8143d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('{')) { 8153d58139fSopenharmony_ci return -1; 8163d58139fSopenharmony_ci } 8173d58139fSopenharmony_ci#endif 8183d58139fSopenharmony_ci ++fmt; 8193d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('^')) { 8203d58139fSopenharmony_ci ++fmt; 8213d58139fSopenharmony_ci } 8223d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR(']')) { 8233d58139fSopenharmony_ci ++fmt; 8243d58139fSopenharmony_ci } 8253d58139fSopenharmony_ci while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { 8263d58139fSopenharmony_ci ++fmt; 8273d58139fSopenharmony_ci } 8283d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('\0')) { 8293d58139fSopenharmony_ci return -1; /* Trunc'd format string */ 8303d58139fSopenharmony_ci } 8313d58139fSopenharmony_ci } 8323d58139fSopenharmony_ci *convChr = ch; 8333d58139fSopenharmony_ci return 0; 8343d58139fSopenharmony_ci} 8353d58139fSopenharmony_ci 8363d58139fSopenharmony_ci/* 8373d58139fSopenharmony_ci * Add L'\0' for wchar string , add '\0' for char string 8383d58139fSopenharmony_ci */ 8393d58139fSopenharmony_ciSECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec) 8403d58139fSopenharmony_ci{ 8413d58139fSopenharmony_ci if (spec->suppress == 0) { 8423d58139fSopenharmony_ci *(char *)ptr = '\0'; 8433d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART 8443d58139fSopenharmony_ci if (spec->isWCharOrLong > 0) { 8453d58139fSopenharmony_ci *(wchar_t UNALIGNED *)ptr = L'\0'; 8463d58139fSopenharmony_ci } 8473d58139fSopenharmony_ci#endif 8483d58139fSopenharmony_ci } 8493d58139fSopenharmony_ci} 8503d58139fSopenharmony_ci 8513d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeClearArg(SecScanSpec *spec, va_list argList) 8523d58139fSopenharmony_ci{ 8533d58139fSopenharmony_ci va_list argListSave; /* Backup for argList value, this variable don't need initialized */ 8543d58139fSopenharmony_ci (void)SECUREC_MEMSET_FUNC_OPT(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */ 8553d58139fSopenharmony_ci#if defined(va_copy) 8563d58139fSopenharmony_ci va_copy(argListSave, argList); 8573d58139fSopenharmony_ci#elif defined(__va_copy) /* For vxworks */ 8583d58139fSopenharmony_ci __va_copy(argListSave, argList); 8593d58139fSopenharmony_ci#else 8603d58139fSopenharmony_ci argListSave = argList; 8613d58139fSopenharmony_ci#endif 8623d58139fSopenharmony_ci spec->argPtr = (void *)va_arg(argListSave, void *); 8633d58139fSopenharmony_ci /* Get the next argument, size of the array in characters */ 8643d58139fSopenharmony_ci /* Use 0xffffffffUL mask to Support pass integer as array length */ 8653d58139fSopenharmony_ci spec->arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xffffffffUL; 8663d58139fSopenharmony_ci va_end(argListSave); 8673d58139fSopenharmony_ci /* To clear e438 last value assigned not used , the compiler will optimize this code */ 8683d58139fSopenharmony_ci (void)argListSave; 8693d58139fSopenharmony_ci} 8703d58139fSopenharmony_ci 8713d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 8723d58139fSopenharmony_ci/* 8733d58139fSopenharmony_ci * Clean up the first %s %c buffer to zero for wchar version 8743d58139fSopenharmony_ci */ 8753d58139fSopenharmony_civoid SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList) 8763d58139fSopenharmony_ci#else 8773d58139fSopenharmony_ci/* 8783d58139fSopenharmony_ci * Clean up the first %s %c buffer to zero for char version 8793d58139fSopenharmony_ci */ 8803d58139fSopenharmony_civoid SecClearDestBuf(const char *buffer, const char *format, va_list argList) 8813d58139fSopenharmony_ci#endif 8823d58139fSopenharmony_ci{ 8833d58139fSopenharmony_ci SecScanSpec spec; 8843d58139fSopenharmony_ci int convChr = 0; 8853d58139fSopenharmony_ci const SecUnsignedChar *fmt = (const SecUnsignedChar *)format; 8863d58139fSopenharmony_ci 8873d58139fSopenharmony_ci /* Find first % */ 8883d58139fSopenharmony_ci while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) { 8893d58139fSopenharmony_ci ++fmt; 8903d58139fSopenharmony_ci } 8913d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('\0')) { 8923d58139fSopenharmony_ci return; 8933d58139fSopenharmony_ci } 8943d58139fSopenharmony_ci 8953d58139fSopenharmony_ci SecSetDefaultScanSpec(&spec); 8963d58139fSopenharmony_ci if (SecDecodeScanFlag(&fmt, &spec) != 0) { 8973d58139fSopenharmony_ci return; 8983d58139fSopenharmony_ci } 8993d58139fSopenharmony_ci 9003d58139fSopenharmony_ci /* Update wchar flag for %S %C */ 9013d58139fSopenharmony_ci SecUpdateWcharFlagByType(*fmt, &spec); 9023d58139fSopenharmony_ci if (spec.suppress != 0) { 9033d58139fSopenharmony_ci return; 9043d58139fSopenharmony_ci } 9053d58139fSopenharmony_ci 9063d58139fSopenharmony_ci if (SecDecodeClearFormat(fmt, &convChr) != 0) { 9073d58139fSopenharmony_ci return; 9083d58139fSopenharmony_ci } 9093d58139fSopenharmony_ci 9103d58139fSopenharmony_ci if (*buffer != SECUREC_CHAR('\0') && convChr != 's') { 9113d58139fSopenharmony_ci /* 9123d58139fSopenharmony_ci * When buffer not empty just clear %s. 9133d58139fSopenharmony_ci * Example call sscanf by argment of (" \n", "%s", s, sizeof(s)) 9143d58139fSopenharmony_ci */ 9153d58139fSopenharmony_ci return; 9163d58139fSopenharmony_ci } 9173d58139fSopenharmony_ci 9183d58139fSopenharmony_ci SecDecodeClearArg(&spec, argList); 9193d58139fSopenharmony_ci /* There is no need to judge the upper limit */ 9203d58139fSopenharmony_ci if (spec.arrayWidth == 0 || spec.argPtr == NULL) { 9213d58139fSopenharmony_ci return; 9223d58139fSopenharmony_ci } 9233d58139fSopenharmony_ci /* Clear one char */ 9243d58139fSopenharmony_ci SecAddEndingZero(spec.argPtr, &spec); 9253d58139fSopenharmony_ci return; 9263d58139fSopenharmony_ci} 9273d58139fSopenharmony_ci 9283d58139fSopenharmony_ci/* 9293d58139fSopenharmony_ci * Assign number to output buffer 9303d58139fSopenharmony_ci */ 9313d58139fSopenharmony_ciSECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec) 9323d58139fSopenharmony_ci{ 9333d58139fSopenharmony_ci void *argPtr = spec->argPtr; 9343d58139fSopenharmony_ci if (spec->numberArgType != 0) { 9353d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM) 9363d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM_COMP) 9373d58139fSopenharmony_ci *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); 9383d58139fSopenharmony_ci#else 9393d58139fSopenharmony_ci /* Take number64 as unsigned number unsigned to int clear Compile warning */ 9403d58139fSopenharmony_ci *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64)); 9413d58139fSopenharmony_ci#endif 9423d58139fSopenharmony_ci#else 9433d58139fSopenharmony_ci /* Take number64 as unsigned number */ 9443d58139fSopenharmony_ci *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); 9453d58139fSopenharmony_ci#endif 9463d58139fSopenharmony_ci return; 9473d58139fSopenharmony_ci } 9483d58139fSopenharmony_ci if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) { 9493d58139fSopenharmony_ci /* Take number as unsigned number */ 9503d58139fSopenharmony_ci *(long UNALIGNED *)argPtr = (long)(spec->number); 9513d58139fSopenharmony_ci } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 9523d58139fSopenharmony_ci *(int UNALIGNED *)argPtr = (int)(spec->number); 9533d58139fSopenharmony_ci } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) { 9543d58139fSopenharmony_ci /* Take number as unsigned number */ 9553d58139fSopenharmony_ci *(short UNALIGNED *)argPtr = (short)(spec->number); 9563d58139fSopenharmony_ci } else { /* < 0 for hh format modifier */ 9573d58139fSopenharmony_ci /* Take number as unsigned number */ 9583d58139fSopenharmony_ci *(char UNALIGNED *)argPtr = (char)(spec->number); 9593d58139fSopenharmony_ci } 9603d58139fSopenharmony_ci} 9613d58139fSopenharmony_ci 9623d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 9633d58139fSopenharmony_ci/* 9643d58139fSopenharmony_ci * Judge the long bit width 9653d58139fSopenharmony_ci */ 9663d58139fSopenharmony_ciSECUREC_INLINE int SecIsLongBitEqual(int bitNum) 9673d58139fSopenharmony_ci{ 9683d58139fSopenharmony_ci return (int)((unsigned int)bitNum == SECUREC_LONG_BIT_NUM); 9693d58139fSopenharmony_ci} 9703d58139fSopenharmony_ci#endif 9713d58139fSopenharmony_ci 9723d58139fSopenharmony_ci/* 9733d58139fSopenharmony_ci * Convert hexadecimal characters to decimal value 9743d58139fSopenharmony_ci */ 9753d58139fSopenharmony_ciSECUREC_INLINE int SecHexValueOfChar(SecInt ch) 9763d58139fSopenharmony_ci{ 9773d58139fSopenharmony_ci /* Use isdigit Causing tool false alarms */ 9783d58139fSopenharmony_ci return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') : 9793d58139fSopenharmony_ci ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */ 9803d58139fSopenharmony_ci} 9813d58139fSopenharmony_ci 9823d58139fSopenharmony_ci/* 9833d58139fSopenharmony_ci * Parse decimal character to integer for 32bit . 9843d58139fSopenharmony_ci */ 9853d58139fSopenharmony_cistatic void SecDecodeNumberDecimal(SecScanSpec *spec) 9863d58139fSopenharmony_ci{ 9873d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 9883d58139fSopenharmony_ci unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN; 9893d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 9903d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 9913d58139fSopenharmony_ci decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN; 9923d58139fSopenharmony_ci } 9933d58139fSopenharmony_ci#endif 9943d58139fSopenharmony_ci if (spec->number > decimalEdge) { 9953d58139fSopenharmony_ci spec->beyondMax = 1; 9963d58139fSopenharmony_ci } 9973d58139fSopenharmony_ci#endif 9983d58139fSopenharmony_ci spec->number = SECUREC_MUL_TEN(spec->number); 9993d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 10003d58139fSopenharmony_ci if (spec->number == SECUREC_MUL_TEN(decimalEdge)) { 10013d58139fSopenharmony_ci /* This code is specially converted to unsigned long type for compatibility */ 10023d58139fSopenharmony_ci SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number; 10033d58139fSopenharmony_ci if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) { 10043d58139fSopenharmony_ci spec->beyondMax = 1; 10053d58139fSopenharmony_ci } 10063d58139fSopenharmony_ci } 10073d58139fSopenharmony_ci#endif 10083d58139fSopenharmony_ci spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 10093d58139fSopenharmony_ci} 10103d58139fSopenharmony_ci 10113d58139fSopenharmony_ci/* 10123d58139fSopenharmony_ci * Parse Hex character to integer for 32bit . 10133d58139fSopenharmony_ci */ 10143d58139fSopenharmony_cistatic void SecDecodeNumberHex(SecScanSpec *spec) 10153d58139fSopenharmony_ci{ 10163d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 10173d58139fSopenharmony_ci if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) { 10183d58139fSopenharmony_ci spec->beyondMax = 1; 10193d58139fSopenharmony_ci } 10203d58139fSopenharmony_ci#endif 10213d58139fSopenharmony_ci spec->number = SECUREC_MUL_SIXTEEN(spec->number); 10223d58139fSopenharmony_ci spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch); 10233d58139fSopenharmony_ci} 10243d58139fSopenharmony_ci 10253d58139fSopenharmony_ci/* 10263d58139fSopenharmony_ci * Parse Octal character to integer for 32bit . 10273d58139fSopenharmony_ci */ 10283d58139fSopenharmony_cistatic void SecDecodeNumberOctal(SecScanSpec *spec) 10293d58139fSopenharmony_ci{ 10303d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 10313d58139fSopenharmony_ci if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) { 10323d58139fSopenharmony_ci spec->beyondMax = 1; 10333d58139fSopenharmony_ci } 10343d58139fSopenharmony_ci#endif 10353d58139fSopenharmony_ci spec->number = SECUREC_MUL_EIGHT(spec->number); 10363d58139fSopenharmony_ci spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 10373d58139fSopenharmony_ci} 10383d58139fSopenharmony_ci 10393d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 10403d58139fSopenharmony_ci/* Compatible with integer negative values other than int */ 10413d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec) 10423d58139fSopenharmony_ci{ 10433d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 10443d58139fSopenharmony_ci if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) { 10453d58139fSopenharmony_ci spec->number = SECUREC_MIN_LONG_NEG_VALUE; 10463d58139fSopenharmony_ci } else { 10473d58139fSopenharmony_ci spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 10483d58139fSopenharmony_ci } 10493d58139fSopenharmony_ci if (spec->beyondMax != 0) { 10503d58139fSopenharmony_ci if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) { 10513d58139fSopenharmony_ci spec->number = 0; 10523d58139fSopenharmony_ci } 10533d58139fSopenharmony_ci if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { 10543d58139fSopenharmony_ci spec->number = SECUREC_MIN_LONG_NEG_VALUE; 10553d58139fSopenharmony_ci } 10563d58139fSopenharmony_ci } 10573d58139fSopenharmony_ci } else { /* For o, u, x, X, p */ 10583d58139fSopenharmony_ci spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 10593d58139fSopenharmony_ci if (spec->beyondMax != 0) { 10603d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 10613d58139fSopenharmony_ci } 10623d58139fSopenharmony_ci } 10633d58139fSopenharmony_ci} 10643d58139fSopenharmony_ci/* Compatible processing of integer negative numbers */ 10653d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec) 10663d58139fSopenharmony_ci{ 10673d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 10683d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 10693d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 10703d58139fSopenharmony_ci if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) { 10713d58139fSopenharmony_ci spec->number = 0; 10723d58139fSopenharmony_ci } else { 10733d58139fSopenharmony_ci spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 10743d58139fSopenharmony_ci } 10753d58139fSopenharmony_ci } 10763d58139fSopenharmony_ci#else 10773d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 10783d58139fSopenharmony_ci if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) { 10793d58139fSopenharmony_ci spec->number = SECUREC_MIN_32BITS_NEG_VALUE; 10803d58139fSopenharmony_ci } else { 10813d58139fSopenharmony_ci spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 10823d58139fSopenharmony_ci } 10833d58139fSopenharmony_ci } 10843d58139fSopenharmony_ci#endif 10853d58139fSopenharmony_ci if (spec->beyondMax != 0) { 10863d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 10873d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 10883d58139fSopenharmony_ci spec->number = 0; 10893d58139fSopenharmony_ci } 10903d58139fSopenharmony_ci#else 10913d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 10923d58139fSopenharmony_ci spec->number = SECUREC_MIN_32BITS_NEG_VALUE; 10933d58139fSopenharmony_ci } 10943d58139fSopenharmony_ci#endif 10953d58139fSopenharmony_ci } 10963d58139fSopenharmony_ci } else { /* For o, u, x, X ,p */ 10973d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 10983d58139fSopenharmony_ci if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) { 10993d58139fSopenharmony_ci spec->number = SECUREC_MAX_32BITS_VALUE; 11003d58139fSopenharmony_ci } else { 11013d58139fSopenharmony_ci spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 11023d58139fSopenharmony_ci } 11033d58139fSopenharmony_ci#else 11043d58139fSopenharmony_ci spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 11053d58139fSopenharmony_ci#endif 11063d58139fSopenharmony_ci if (spec->beyondMax != 0) { 11073d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 11083d58139fSopenharmony_ci } 11093d58139fSopenharmony_ci } 11103d58139fSopenharmony_ci} 11113d58139fSopenharmony_ci 11123d58139fSopenharmony_ci/* Compatible with integer positive values other than int */ 11133d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec) 11143d58139fSopenharmony_ci{ 11153d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 11163d58139fSopenharmony_ci if (spec->number > SECUREC_MAX_LONG_POS_VALUE) { 11173d58139fSopenharmony_ci spec->number = SECUREC_MAX_LONG_POS_VALUE; 11183d58139fSopenharmony_ci } 11193d58139fSopenharmony_ci if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) { 11203d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 11213d58139fSopenharmony_ci } 11223d58139fSopenharmony_ci if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { 11233d58139fSopenharmony_ci spec->number = SECUREC_MAX_LONG_POS_VALUE; 11243d58139fSopenharmony_ci } 11253d58139fSopenharmony_ci } else { 11263d58139fSopenharmony_ci if (spec->beyondMax != 0) { 11273d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 11283d58139fSopenharmony_ci } 11293d58139fSopenharmony_ci } 11303d58139fSopenharmony_ci} 11313d58139fSopenharmony_ci 11323d58139fSopenharmony_ci/* Compatible processing of integer positive numbers */ 11333d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec) 11343d58139fSopenharmony_ci{ 11353d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 11363d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 11373d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 11383d58139fSopenharmony_ci if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) { 11393d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 11403d58139fSopenharmony_ci } 11413d58139fSopenharmony_ci } 11423d58139fSopenharmony_ci if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 11433d58139fSopenharmony_ci spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 11443d58139fSopenharmony_ci } 11453d58139fSopenharmony_ci#else 11463d58139fSopenharmony_ci if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 11473d58139fSopenharmony_ci if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) { 11483d58139fSopenharmony_ci spec->number = SECUREC_MAX_32BITS_POS_VALUE; 11493d58139fSopenharmony_ci } 11503d58139fSopenharmony_ci } 11513d58139fSopenharmony_ci if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 11523d58139fSopenharmony_ci spec->number = SECUREC_MAX_32BITS_POS_VALUE; 11533d58139fSopenharmony_ci } 11543d58139fSopenharmony_ci#endif 11553d58139fSopenharmony_ci } else { /* For o,u,x,X,p */ 11563d58139fSopenharmony_ci if (spec->beyondMax != 0) { 11573d58139fSopenharmony_ci spec->number = SECUREC_MAX_32BITS_VALUE; 11583d58139fSopenharmony_ci } 11593d58139fSopenharmony_ci } 11603d58139fSopenharmony_ci} 11613d58139fSopenharmony_ci 11623d58139fSopenharmony_ci#endif 11633d58139fSopenharmony_ci 11643d58139fSopenharmony_ci/* 11653d58139fSopenharmony_ci * Parse decimal character to integer for 64bit . 11663d58139fSopenharmony_ci */ 11673d58139fSopenharmony_cistatic void SecDecodeNumber64Decimal(SecScanSpec *spec) 11683d58139fSopenharmony_ci{ 11693d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 11703d58139fSopenharmony_ci if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) { 11713d58139fSopenharmony_ci spec->beyondMax = 1; 11723d58139fSopenharmony_ci } 11733d58139fSopenharmony_ci#endif 11743d58139fSopenharmony_ci spec->number64 = SECUREC_MUL_TEN(spec->number64); 11753d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 11763d58139fSopenharmony_ci if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) { 11773d58139fSopenharmony_ci SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64; 11783d58139fSopenharmony_ci if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) { 11793d58139fSopenharmony_ci spec->beyondMax = 1; 11803d58139fSopenharmony_ci } 11813d58139fSopenharmony_ci } 11823d58139fSopenharmony_ci#endif 11833d58139fSopenharmony_ci spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 11843d58139fSopenharmony_ci} 11853d58139fSopenharmony_ci 11863d58139fSopenharmony_ci/* 11873d58139fSopenharmony_ci * Parse Hex character to integer for 64bit . 11883d58139fSopenharmony_ci */ 11893d58139fSopenharmony_cistatic void SecDecodeNumber64Hex(SecScanSpec *spec) 11903d58139fSopenharmony_ci{ 11913d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 11923d58139fSopenharmony_ci if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) { 11933d58139fSopenharmony_ci spec->beyondMax = 1; 11943d58139fSopenharmony_ci } 11953d58139fSopenharmony_ci#endif 11963d58139fSopenharmony_ci spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64); 11973d58139fSopenharmony_ci spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch); 11983d58139fSopenharmony_ci} 11993d58139fSopenharmony_ci 12003d58139fSopenharmony_ci/* 12013d58139fSopenharmony_ci * Parse Octal character to integer for 64bit . 12023d58139fSopenharmony_ci */ 12033d58139fSopenharmony_cistatic void SecDecodeNumber64Octal(SecScanSpec *spec) 12043d58139fSopenharmony_ci{ 12053d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 12063d58139fSopenharmony_ci if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) { 12073d58139fSopenharmony_ci spec->beyondMax = 1; 12083d58139fSopenharmony_ci } 12093d58139fSopenharmony_ci#endif 12103d58139fSopenharmony_ci spec->number64 = SECUREC_MUL_EIGHT(spec->number64); 12113d58139fSopenharmony_ci spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 12123d58139fSopenharmony_ci} 12133d58139fSopenharmony_ci 12143d58139fSopenharmony_ci#define SECUREC_DECODE_NUMBER_FUNC_NUM 2 12153d58139fSopenharmony_ci 12163d58139fSopenharmony_ci/* 12173d58139fSopenharmony_ci * Parse 64-bit integer formatted input, return 0 when ch is a number. 12183d58139fSopenharmony_ci */ 12193d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec) 12203d58139fSopenharmony_ci{ 12213d58139fSopenharmony_ci /* Function name cannot add address symbol, causing 546 alarm */ 12223d58139fSopenharmony_ci static void (* const secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 12233d58139fSopenharmony_ci SecDecodeNumberHex, SecDecodeNumber64Hex 12243d58139fSopenharmony_ci }; 12253d58139fSopenharmony_ci static void (* const secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 12263d58139fSopenharmony_ci SecDecodeNumberOctal, SecDecodeNumber64Octal 12273d58139fSopenharmony_ci }; 12283d58139fSopenharmony_ci static void (* const secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 12293d58139fSopenharmony_ci SecDecodeNumberDecimal, SecDecodeNumber64Decimal 12303d58139fSopenharmony_ci }; 12313d58139fSopenharmony_ci if (spec->convChr == 'x' || spec->convChr == 'p') { 12323d58139fSopenharmony_ci if (SecIsXdigit(spec->ch) != 0) { 12333d58139fSopenharmony_ci (*secDecodeNumberHex[spec->numberArgType])(spec); 12343d58139fSopenharmony_ci } else { 12353d58139fSopenharmony_ci return -1; 12363d58139fSopenharmony_ci } 12373d58139fSopenharmony_ci return 0; 12383d58139fSopenharmony_ci } 12393d58139fSopenharmony_ci if (SecIsDigit(spec->ch) == 0) { 12403d58139fSopenharmony_ci return -1; 12413d58139fSopenharmony_ci } 12423d58139fSopenharmony_ci if (spec->convChr == 'o') { 12433d58139fSopenharmony_ci if (spec->ch < SECUREC_CHAR('8')) { /* Octal maximum limit '8' */ 12443d58139fSopenharmony_ci (*secDecodeNumberOctal[spec->numberArgType])(spec); 12453d58139fSopenharmony_ci } else { 12463d58139fSopenharmony_ci return -1; 12473d58139fSopenharmony_ci } 12483d58139fSopenharmony_ci } else { /* The convChr is 'd' */ 12493d58139fSopenharmony_ci (*secDecodeNumberDecimal[spec->numberArgType])(spec); 12503d58139fSopenharmony_ci } 12513d58139fSopenharmony_ci return 0; 12523d58139fSopenharmony_ci} 12533d58139fSopenharmony_ci 12543d58139fSopenharmony_ci/* 12553d58139fSopenharmony_ci * Complete the final 32-bit integer formatted input 12563d58139fSopenharmony_ci */ 12573d58139fSopenharmony_cistatic void SecFinishNumber(SecScanSpec *spec) 12583d58139fSopenharmony_ci{ 12593d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 12603d58139fSopenharmony_ci if (spec->negative != 0) { 12613d58139fSopenharmony_ci if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 12623d58139fSopenharmony_ci SecFinishNumberNegativeInt(spec); 12633d58139fSopenharmony_ci } else { 12643d58139fSopenharmony_ci SecFinishNumberNegativeOther(spec); 12653d58139fSopenharmony_ci } 12663d58139fSopenharmony_ci } else { 12673d58139fSopenharmony_ci if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 12683d58139fSopenharmony_ci SecFinishNumberPositiveInt(spec); 12693d58139fSopenharmony_ci } else { 12703d58139fSopenharmony_ci SecFinishNumberPositiveOther(spec); 12713d58139fSopenharmony_ci } 12723d58139fSopenharmony_ci } 12733d58139fSopenharmony_ci#else 12743d58139fSopenharmony_ci if (spec->negative != 0) { 12753d58139fSopenharmony_ci#if defined(__hpux) 12763d58139fSopenharmony_ci if (spec->oriConvChr != 'p') { 12773d58139fSopenharmony_ci spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 12783d58139fSopenharmony_ci } 12793d58139fSopenharmony_ci#else 12803d58139fSopenharmony_ci spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 12813d58139fSopenharmony_ci#endif 12823d58139fSopenharmony_ci } 12833d58139fSopenharmony_ci#endif 12843d58139fSopenharmony_ci return; 12853d58139fSopenharmony_ci} 12863d58139fSopenharmony_ci 12873d58139fSopenharmony_ci/* 12883d58139fSopenharmony_ci * Complete the final 64-bit integer formatted input 12893d58139fSopenharmony_ci */ 12903d58139fSopenharmony_cistatic void SecFinishNumber64(SecScanSpec *spec) 12913d58139fSopenharmony_ci{ 12923d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 12933d58139fSopenharmony_ci if (spec->negative != 0) { 12943d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 12953d58139fSopenharmony_ci if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) { 12963d58139fSopenharmony_ci spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; 12973d58139fSopenharmony_ci } else { 12983d58139fSopenharmony_ci spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 12993d58139fSopenharmony_ci } 13003d58139fSopenharmony_ci if (spec->beyondMax != 0) { 13013d58139fSopenharmony_ci spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; 13023d58139fSopenharmony_ci } 13033d58139fSopenharmony_ci } else { /* For o, u, x, X, p */ 13043d58139fSopenharmony_ci spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 13053d58139fSopenharmony_ci if (spec->beyondMax != 0) { 13063d58139fSopenharmony_ci spec->number64 = SECUREC_MAX_64BITS_VALUE; 13073d58139fSopenharmony_ci } 13083d58139fSopenharmony_ci } 13093d58139fSopenharmony_ci } else { 13103d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 13113d58139fSopenharmony_ci if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) { 13123d58139fSopenharmony_ci spec->number64 = SECUREC_MAX_64BITS_POS_VALUE; 13133d58139fSopenharmony_ci } 13143d58139fSopenharmony_ci if (spec->beyondMax != 0) { 13153d58139fSopenharmony_ci spec->number64 = SECUREC_MAX_64BITS_POS_VALUE; 13163d58139fSopenharmony_ci } 13173d58139fSopenharmony_ci } else { 13183d58139fSopenharmony_ci if (spec->beyondMax != 0) { 13193d58139fSopenharmony_ci spec->number64 = SECUREC_MAX_64BITS_VALUE; 13203d58139fSopenharmony_ci } 13213d58139fSopenharmony_ci } 13223d58139fSopenharmony_ci } 13233d58139fSopenharmony_ci#else 13243d58139fSopenharmony_ci if (spec->negative != 0) { 13253d58139fSopenharmony_ci#if defined(__hpux) 13263d58139fSopenharmony_ci if (spec->oriConvChr != 'p') { 13273d58139fSopenharmony_ci spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 13283d58139fSopenharmony_ci } 13293d58139fSopenharmony_ci#else 13303d58139fSopenharmony_ci spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 13313d58139fSopenharmony_ci#endif 13323d58139fSopenharmony_ci } 13333d58139fSopenharmony_ci#endif 13343d58139fSopenharmony_ci return; 13353d58139fSopenharmony_ci} 13363d58139fSopenharmony_ci 13373d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE 13383d58139fSopenharmony_ci 13393d58139fSopenharmony_ci/* 13403d58139fSopenharmony_ci * Adjust the pointer position of the file stream 13413d58139fSopenharmony_ci */ 13423d58139fSopenharmony_ciSECUREC_INLINE void SecSeekStream(SecFileStream *stream) 13433d58139fSopenharmony_ci{ 13443d58139fSopenharmony_ci if (stream->count == 0) { 13453d58139fSopenharmony_ci if (feof(stream->pf) != 0) { 13463d58139fSopenharmony_ci /* File pointer at the end of file, don't need to seek back */ 13473d58139fSopenharmony_ci stream->base[0] = '\0'; 13483d58139fSopenharmony_ci return; 13493d58139fSopenharmony_ci } 13503d58139fSopenharmony_ci } 13513d58139fSopenharmony_ci /* Seek to original position, for file read, but nothing to input */ 13523d58139fSopenharmony_ci if (fseek(stream->pf, stream->oriFilePos, SEEK_SET) != 0) { 13533d58139fSopenharmony_ci /* Seek failed, ignore it */ 13543d58139fSopenharmony_ci stream->oriFilePos = 0; 13553d58139fSopenharmony_ci return; 13563d58139fSopenharmony_ci } 13573d58139fSopenharmony_ci 13583d58139fSopenharmony_ci if (stream->fileRealRead > 0) { /* Do not seek without input data */ 13593d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 13603d58139fSopenharmony_ci size_t residue = stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE; 13613d58139fSopenharmony_ci size_t loops; 13623d58139fSopenharmony_ci for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) { 13633d58139fSopenharmony_ci if (fread(stream->base, (size_t)SECUREC_BUFFERED_BLOK_SIZE, (size_t)1, stream->pf) != (size_t)1) { 13643d58139fSopenharmony_ci break; 13653d58139fSopenharmony_ci } 13663d58139fSopenharmony_ci } 13673d58139fSopenharmony_ci if (residue != 0) { 13683d58139fSopenharmony_ci long curFilePos; 13693d58139fSopenharmony_ci if (fread(stream->base, residue, (size_t)1, stream->pf) != (size_t)1) { 13703d58139fSopenharmony_ci return; 13713d58139fSopenharmony_ci } 13723d58139fSopenharmony_ci curFilePos = ftell(stream->pf); 13733d58139fSopenharmony_ci if (curFilePos < stream->oriFilePos || 13743d58139fSopenharmony_ci (size_t)(unsigned long)(curFilePos - stream->oriFilePos) < stream->fileRealRead) { 13753d58139fSopenharmony_ci /* Try to remedy the problem */ 13763d58139fSopenharmony_ci long adjustNum = (long)(stream->fileRealRead - (size_t)(unsigned long)(curFilePos - stream->oriFilePos)); 13773d58139fSopenharmony_ci (void)fseek(stream->pf, adjustNum, SEEK_CUR); 13783d58139fSopenharmony_ci } 13793d58139fSopenharmony_ci } 13803d58139fSopenharmony_ci#else 13813d58139fSopenharmony_ci /* Seek from oriFilePos. Regardless of the integer sign problem, call scanf will not read very large data */ 13823d58139fSopenharmony_ci if (fseek(stream->pf, (long)stream->fileRealRead, SEEK_CUR) != 0) { 13833d58139fSopenharmony_ci /* Seek failed, ignore it */ 13843d58139fSopenharmony_ci stream->oriFilePos = 0; 13853d58139fSopenharmony_ci return; 13863d58139fSopenharmony_ci } 13873d58139fSopenharmony_ci#endif 13883d58139fSopenharmony_ci } 13893d58139fSopenharmony_ci return; 13903d58139fSopenharmony_ci} 13913d58139fSopenharmony_ci 13923d58139fSopenharmony_ci/* 13933d58139fSopenharmony_ci * Adjust the pointer position of the file stream and free memory 13943d58139fSopenharmony_ci */ 13953d58139fSopenharmony_ciSECUREC_INLINE void SecAdjustStream(SecFileStream *stream) 13963d58139fSopenharmony_ci{ 13973d58139fSopenharmony_ci if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0 && stream->base != NULL) { 13983d58139fSopenharmony_ci SecSeekStream(stream); 13993d58139fSopenharmony_ci SECUREC_FREE(stream->base); 14003d58139fSopenharmony_ci stream->base = NULL; 14013d58139fSopenharmony_ci } 14023d58139fSopenharmony_ci return; 14033d58139fSopenharmony_ci} 14043d58139fSopenharmony_ci#endif 14053d58139fSopenharmony_ci 14063d58139fSopenharmony_ciSECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format) 14073d58139fSopenharmony_ci{ 14083d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 14093d58139fSopenharmony_ci while (SecIsSpace((SecInt)(int)(*fmt)) != 0) { 14103d58139fSopenharmony_ci ++fmt; 14113d58139fSopenharmony_ci } 14123d58139fSopenharmony_ci *format = fmt; 14133d58139fSopenharmony_ci} 14143d58139fSopenharmony_ci 14153d58139fSopenharmony_ci#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) 14163d58139fSopenharmony_ci/* 14173d58139fSopenharmony_ci * Handling multi-character characters 14183d58139fSopenharmony_ci */ 14193d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream) 14203d58139fSopenharmony_ci{ 14213d58139fSopenharmony_ci#if SECUREC_HAVE_MBTOWC 14223d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 14233d58139fSopenharmony_ci int ch1 = (int)spec->ch; 14243d58139fSopenharmony_ci int ch2 = SecGetChar(stream, &(spec->charCount)); 14253d58139fSopenharmony_ci spec->ch = (SecInt)ch2; 14263d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) { 14273d58139fSopenharmony_ci /* in console mode, ungetc twice may cause problem */ 14283d58139fSopenharmony_ci SecUnGetChar(ch2, stream, &(spec->charCount)); 14293d58139fSopenharmony_ci SecUnGetChar(ch1, stream, &(spec->charCount)); 14303d58139fSopenharmony_ci return -1; 14313d58139fSopenharmony_ci } 14323d58139fSopenharmony_ci ++fmt; 14333d58139fSopenharmony_ci if ((unsigned int)MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE && 14343d58139fSopenharmony_ci (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) && 14353d58139fSopenharmony_ci (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) { 14363d58139fSopenharmony_ci /* This char is very likely to be a UTF-8 char */ 14373d58139fSopenharmony_ci wchar_t tempWChar; 14383d58139fSopenharmony_ci char temp[SECUREC_MULTI_BYTE_MAX_LEN]; 14393d58139fSopenharmony_ci int ch3 = (int)SecGetChar(stream, &(spec->charCount)); 14403d58139fSopenharmony_ci spec->ch = (SecInt)ch3; 14413d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) { 14423d58139fSopenharmony_ci SecUnGetChar(ch3, stream, &(spec->charCount)); 14433d58139fSopenharmony_ci return -1; 14443d58139fSopenharmony_ci } 14453d58139fSopenharmony_ci temp[0] = (char)ch1; 14463d58139fSopenharmony_ci temp[1] = (char)ch2; /* 1 index of second character */ 14473d58139fSopenharmony_ci temp[2] = (char)ch3; /* 2 index of third character */ 14483d58139fSopenharmony_ci temp[3] = '\0'; /* 3 of string terminator position */ 14493d58139fSopenharmony_ci if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) { 14503d58139fSopenharmony_ci /* Succeed */ 14513d58139fSopenharmony_ci ++fmt; 14523d58139fSopenharmony_ci --spec->charCount; 14533d58139fSopenharmony_ci } else { 14543d58139fSopenharmony_ci SecUnGetChar(ch3, stream, &(spec->charCount)); 14553d58139fSopenharmony_ci } 14563d58139fSopenharmony_ci } 14573d58139fSopenharmony_ci --spec->charCount; /* Only count as one character read */ 14583d58139fSopenharmony_ci *format = fmt; 14593d58139fSopenharmony_ci return 0; 14603d58139fSopenharmony_ci#else 14613d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 14623d58139fSopenharmony_ci (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 14633d58139fSopenharmony_ci return -1; 14643d58139fSopenharmony_ci#endif 14653d58139fSopenharmony_ci} 14663d58139fSopenharmony_ci 14673d58139fSopenharmony_ciSECUREC_INLINE int SecFilterWcharInFormat(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream) 14683d58139fSopenharmony_ci{ 14693d58139fSopenharmony_ci if (SecIsLeadByte(spec->ch) != 0) { 14703d58139fSopenharmony_ci if (SecDecodeLeadByte(spec, format, stream) != 0) { 14713d58139fSopenharmony_ci return -1; 14723d58139fSopenharmony_ci } 14733d58139fSopenharmony_ci } 14743d58139fSopenharmony_ci return 0; 14753d58139fSopenharmony_ci} 14763d58139fSopenharmony_ci#endif 14773d58139fSopenharmony_ci 14783d58139fSopenharmony_ci/* 14793d58139fSopenharmony_ci * Resolving sequence of characters from %[ format, format wile point to ']' 14803d58139fSopenharmony_ci */ 14813d58139fSopenharmony_ciSECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable) 14823d58139fSopenharmony_ci{ 14833d58139fSopenharmony_ci const SecUnsignedChar *fmt = *format; 14843d58139fSopenharmony_ci SecUnsignedChar prevChar = 0; 14853d58139fSopenharmony_ci#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 14863d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('{')) { 14873d58139fSopenharmony_ci return -1; 14883d58139fSopenharmony_ci } 14893d58139fSopenharmony_ci#endif 14903d58139fSopenharmony_ci /* For building "table" data */ 14913d58139fSopenharmony_ci ++fmt; /* Skip [ */ 14923d58139fSopenharmony_ci bracketTable->mask = 0; /* Set all bits to 0 */ 14933d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR('^')) { 14943d58139fSopenharmony_ci ++fmt; 14953d58139fSopenharmony_ci bracketTable->mask = (unsigned char)0xffU; /* Use 0xffU to set all bits to 1 */ 14963d58139fSopenharmony_ci } 14973d58139fSopenharmony_ci if (*fmt == SECUREC_CHAR(']')) { 14983d58139fSopenharmony_ci prevChar = SECUREC_CHAR(']'); 14993d58139fSopenharmony_ci ++fmt; 15003d58139fSopenharmony_ci SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']')); 15013d58139fSopenharmony_ci } 15023d58139fSopenharmony_ci while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { 15033d58139fSopenharmony_ci SecUnsignedChar expCh = *fmt; 15043d58139fSopenharmony_ci ++fmt; 15053d58139fSopenharmony_ci if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) { 15063d58139fSopenharmony_ci /* Normal character */ 15073d58139fSopenharmony_ci prevChar = expCh; 15083d58139fSopenharmony_ci SecBracketSetBit(bracketTable->table, expCh); 15093d58139fSopenharmony_ci } else { 15103d58139fSopenharmony_ci /* For %[a-z] */ 15113d58139fSopenharmony_ci expCh = *fmt; /* Get end of range */ 15123d58139fSopenharmony_ci ++fmt; 15133d58139fSopenharmony_ci if (prevChar <= expCh) { /* %[a-z] %[a-a] */ 15143d58139fSopenharmony_ci SecBracketSetBitRange(bracketTable->table, prevChar, expCh); 15153d58139fSopenharmony_ci } else { 15163d58139fSopenharmony_ci /* For %[z-a] */ 15173d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 15183d58139fSopenharmony_ci /* Swap start and end characters */ 15193d58139fSopenharmony_ci SecBracketSetBitRange(bracketTable->table, expCh, prevChar); 15203d58139fSopenharmony_ci#else 15213d58139fSopenharmony_ci SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-')); 15223d58139fSopenharmony_ci SecBracketSetBit(bracketTable->table, expCh); 15233d58139fSopenharmony_ci#endif 15243d58139fSopenharmony_ci } 15253d58139fSopenharmony_ci prevChar = 0; 15263d58139fSopenharmony_ci } 15273d58139fSopenharmony_ci } 15283d58139fSopenharmony_ci *format = fmt; 15293d58139fSopenharmony_ci return 0; 15303d58139fSopenharmony_ci} 15313d58139fSopenharmony_ci 15323d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 15333d58139fSopenharmony_ciSECUREC_INLINE int SecInputForWchar(SecScanSpec *spec) 15343d58139fSopenharmony_ci{ 15353d58139fSopenharmony_ci void *endPtr = spec->argPtr; 15363d58139fSopenharmony_ci if (spec->isWCharOrLong > 0) { 15373d58139fSopenharmony_ci *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch; 15383d58139fSopenharmony_ci endPtr = (wchar_t *)endPtr + 1; 15393d58139fSopenharmony_ci --spec->arrayWidth; 15403d58139fSopenharmony_ci } else { 15413d58139fSopenharmony_ci#if SECUREC_HAVE_WCTOMB 15423d58139fSopenharmony_ci int temp; 15433d58139fSopenharmony_ci char tmpBuf[SECUREC_MB_LEN + 1]; 15443d58139fSopenharmony_ci SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch); 15453d58139fSopenharmony_ci SECUREC_END_MASK_MSVC_CRT_WARNING 15463d58139fSopenharmony_ci if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) { 15473d58139fSopenharmony_ci /* If wctomb error, then ignore character */ 15483d58139fSopenharmony_ci return 0; 15493d58139fSopenharmony_ci } 15503d58139fSopenharmony_ci if (((size_t)(unsigned int)temp) > spec->arrayWidth) { 15513d58139fSopenharmony_ci return -1; 15523d58139fSopenharmony_ci } 15533d58139fSopenharmony_ci if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) { 15543d58139fSopenharmony_ci return -1; 15553d58139fSopenharmony_ci } 15563d58139fSopenharmony_ci endPtr = (char *)endPtr + temp; 15573d58139fSopenharmony_ci spec->arrayWidth -= (size_t)(unsigned int)temp; 15583d58139fSopenharmony_ci#else 15593d58139fSopenharmony_ci return -1; 15603d58139fSopenharmony_ci#endif 15613d58139fSopenharmony_ci } 15623d58139fSopenharmony_ci spec->argPtr = endPtr; 15633d58139fSopenharmony_ci return 0; 15643d58139fSopenharmony_ci} 15653d58139fSopenharmony_ci#endif 15663d58139fSopenharmony_ci 15673d58139fSopenharmony_ci#ifndef SECUREC_FOR_WCHAR 15683d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART 15693d58139fSopenharmony_ciSECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream) 15703d58139fSopenharmony_ci{ 15713d58139fSopenharmony_ci wchar_t tempWChar = L'?'; /* Set default char is ? */ 15723d58139fSopenharmony_ci#if SECUREC_HAVE_MBTOWC 15733d58139fSopenharmony_ci char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1]; 15743d58139fSopenharmony_ci temp[0] = (char)spec->ch; 15753d58139fSopenharmony_ci temp[1] = '\0'; 15763d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 15773d58139fSopenharmony_ci if (SecIsLeadByte(spec->ch) != 0) { 15783d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 15793d58139fSopenharmony_ci temp[1] = (char)spec->ch; 15803d58139fSopenharmony_ci temp[2] = '\0'; /* 2 of string terminator position */ 15813d58139fSopenharmony_ci } 15823d58139fSopenharmony_ci if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { 15833d58139fSopenharmony_ci /* No string termination error for tool */ 15843d58139fSopenharmony_ci tempWChar = L'?'; 15853d58139fSopenharmony_ci } 15863d58139fSopenharmony_ci#else 15873d58139fSopenharmony_ci if (SecIsLeadByte(spec->ch) != 0) { 15883d58139fSopenharmony_ci int convRes = 0; 15893d58139fSopenharmony_ci int di = 1; 15903d58139fSopenharmony_ci /* On Linux like system, the string is encoded in UTF-8 */ 15913d58139fSopenharmony_ci while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) { 15923d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 15933d58139fSopenharmony_ci temp[di] = (char)spec->ch; 15943d58139fSopenharmony_ci ++di; 15953d58139fSopenharmony_ci temp[di] = '\0'; 15963d58139fSopenharmony_ci convRes = mbtowc(&tempWChar, temp, sizeof(temp)); 15973d58139fSopenharmony_ci } 15983d58139fSopenharmony_ci if (convRes <= 0) { 15993d58139fSopenharmony_ci tempWChar = L'?'; 16003d58139fSopenharmony_ci } 16013d58139fSopenharmony_ci } else { 16023d58139fSopenharmony_ci if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { 16033d58139fSopenharmony_ci tempWChar = L'?'; 16043d58139fSopenharmony_ci } 16053d58139fSopenharmony_ci } 16063d58139fSopenharmony_ci#endif 16073d58139fSopenharmony_ci#else 16083d58139fSopenharmony_ci (void)spec; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 16093d58139fSopenharmony_ci (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 16103d58139fSopenharmony_ci#endif /* SECUREC_HAVE_MBTOWC */ 16113d58139fSopenharmony_ci 16123d58139fSopenharmony_ci return tempWChar; 16133d58139fSopenharmony_ci} 16143d58139fSopenharmony_ci#endif /* SECUREC_HAVE_WCHART */ 16153d58139fSopenharmony_ci 16163d58139fSopenharmony_ciSECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream) 16173d58139fSopenharmony_ci{ 16183d58139fSopenharmony_ci void *endPtr = spec->argPtr; 16193d58139fSopenharmony_ci if (spec->isWCharOrLong > 0) { 16203d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART 16213d58139fSopenharmony_ci *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream); 16223d58139fSopenharmony_ci endPtr = (wchar_t *)endPtr + 1; 16233d58139fSopenharmony_ci --spec->arrayWidth; 16243d58139fSopenharmony_ci#else 16253d58139fSopenharmony_ci (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 16263d58139fSopenharmony_ci return -1; 16273d58139fSopenharmony_ci#endif 16283d58139fSopenharmony_ci } else { 16293d58139fSopenharmony_ci *(char *)endPtr = (char)spec->ch; 16303d58139fSopenharmony_ci endPtr = (char *)endPtr + 1; 16313d58139fSopenharmony_ci --spec->arrayWidth; 16323d58139fSopenharmony_ci } 16333d58139fSopenharmony_ci spec->argPtr = endPtr; 16343d58139fSopenharmony_ci return 0; 16353d58139fSopenharmony_ci} 16363d58139fSopenharmony_ci#endif 16373d58139fSopenharmony_ci 16383d58139fSopenharmony_ci/* 16393d58139fSopenharmony_ci * Scan digital part of %d %i %o %u %x %p. 16403d58139fSopenharmony_ci * Return 0 OK 16413d58139fSopenharmony_ci */ 16423d58139fSopenharmony_ciSECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec) 16433d58139fSopenharmony_ci{ 16443d58139fSopenharmony_ci static void (* const secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 16453d58139fSopenharmony_ci SecFinishNumber, SecFinishNumber64 16463d58139fSopenharmony_ci }; 16473d58139fSopenharmony_ci while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 16483d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 16493d58139fSopenharmony_ci /* Decode ch to number */ 16503d58139fSopenharmony_ci if (SecDecodeNumber(spec) != 0) { 16513d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 16523d58139fSopenharmony_ci break; 16533d58139fSopenharmony_ci } 16543d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 16553d58139fSopenharmony_ci spec->numberState = SECUREC_NUMBER_STATE_STARTED; 16563d58139fSopenharmony_ci } 16573d58139fSopenharmony_ci /* Handling integer negative numbers and beyond max */ 16583d58139fSopenharmony_ci (*secFinishNumber[spec->numberArgType])(spec); 16593d58139fSopenharmony_ci if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) { 16603d58139fSopenharmony_ci return 0; 16613d58139fSopenharmony_ci } 16623d58139fSopenharmony_ci return -1; 16633d58139fSopenharmony_ci} 16643d58139fSopenharmony_ci 16653d58139fSopenharmony_ci/* 16663d58139fSopenharmony_ci * Scan %d %i %o %u %x %p. 16673d58139fSopenharmony_ci * Return 0 OK 16683d58139fSopenharmony_ci */ 16693d58139fSopenharmony_ciSECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec) 16703d58139fSopenharmony_ci{ 16713d58139fSopenharmony_ci /* Character already read */ 16723d58139fSopenharmony_ci if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { 16733d58139fSopenharmony_ci if (spec->ch == SECUREC_CHAR('-')) { 16743d58139fSopenharmony_ci spec->negative = 1; 16753d58139fSopenharmony_ci#if SECUREC_IN_KERNEL 16763d58139fSopenharmony_ci /* In kernel Refuse to enter negative number */ 16773d58139fSopenharmony_ci if (SECUREC_CONVERT_IS_UNSIGNED(spec->oriConvChr)) { 16783d58139fSopenharmony_ci return -1; 16793d58139fSopenharmony_ci } 16803d58139fSopenharmony_ci#endif 16813d58139fSopenharmony_ci } 16823d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Do not need to check width here, must be greater than 0 */ 16833d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); /* Eat + or - */ 16843d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next character, used for the '0' judgments */ 16853d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); /* Not sure if it was actually read, so push back */ 16863d58139fSopenharmony_ci } 16873d58139fSopenharmony_ci 16883d58139fSopenharmony_ci if (spec->oriConvChr == 'i') { 16893d58139fSopenharmony_ci spec->convChr = 'd'; /* The i could be d, o, or x, use d as default */ 16903d58139fSopenharmony_ci } 16913d58139fSopenharmony_ci 16923d58139fSopenharmony_ci if (spec->ch == SECUREC_CHAR('0') && (spec->oriConvChr == 'x' || spec->oriConvChr == 'i') && 16933d58139fSopenharmony_ci SECUREC_FILED_WIDTH_ENOUGH(spec)) { 16943d58139fSopenharmony_ci /* Input string begin with 0, may be 0x123 0X123 0123 0x 01 0yy 09 0 0ab 00 */ 16953d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); 16963d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); /* ch is '0' */ 16973d58139fSopenharmony_ci 16983d58139fSopenharmony_ci /* Read only '0' due to width limitation */ 16993d58139fSopenharmony_ci if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) { 17003d58139fSopenharmony_ci /* The number or number64 in spec has been set 0 */ 17013d58139fSopenharmony_ci return 0; 17023d58139fSopenharmony_ci } 17033d58139fSopenharmony_ci 17043d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next char to check x or X, do not dec width */ 17053d58139fSopenharmony_ci if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) { 17063d58139fSopenharmony_ci spec->convChr = 'x'; 17073d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); /* Make incorrect width for x or X */ 17083d58139fSopenharmony_ci } else { 17093d58139fSopenharmony_ci if (spec->oriConvChr == 'i') { 17103d58139fSopenharmony_ci spec->convChr = 'o'; 17113d58139fSopenharmony_ci } 17123d58139fSopenharmony_ci /* For "0y" "08" "01" "0a" ... ,push the 'y' '8' '1' 'a' back */ 17133d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 17143d58139fSopenharmony_ci /* Since 0 has been read, it indicates that a valid character has been read */ 17153d58139fSopenharmony_ci spec->numberState = SECUREC_NUMBER_STATE_STARTED; 17163d58139fSopenharmony_ci } 17173d58139fSopenharmony_ci } 17183d58139fSopenharmony_ci return SecInputNumberDigital(stream, spec); 17193d58139fSopenharmony_ci} 17203d58139fSopenharmony_ci 17213d58139fSopenharmony_ci/* 17223d58139fSopenharmony_ci * Scan %c %s %[ 17233d58139fSopenharmony_ci * Return 0 OK 17243d58139fSopenharmony_ci */ 17253d58139fSopenharmony_ciSECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec, 17263d58139fSopenharmony_ci const SecBracketTable *bracketTable, int *doneCount) 17273d58139fSopenharmony_ci{ 17283d58139fSopenharmony_ci void *startPtr = spec->argPtr; 17293d58139fSopenharmony_ci int suppressed = 0; 17303d58139fSopenharmony_ci int errNoMem = 0; 17313d58139fSopenharmony_ci 17323d58139fSopenharmony_ci while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 17333d58139fSopenharmony_ci SECUREC_FILED_WIDTH_DEC(spec); 17343d58139fSopenharmony_ci spec->ch = SecGetChar(stream, &(spec->charCount)); 17353d58139fSopenharmony_ci /* 17363d58139fSopenharmony_ci * The char condition or string condition and bracket condition. 17373d58139fSopenharmony_ci * Only supports wide characters with a maximum length of two bytes 17383d58139fSopenharmony_ci */ 17393d58139fSopenharmony_ci if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) != 0 || 17403d58139fSopenharmony_ci SecCanInputString(spec->convChr, spec->ch) != 0 || 17413d58139fSopenharmony_ci SecCanInputForBracket(spec->convChr, spec->ch, bracketTable) != 0)) { 17423d58139fSopenharmony_ci if (spec->suppress != 0) { 17433d58139fSopenharmony_ci /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */ 17443d58139fSopenharmony_ci suppressed = 1; 17453d58139fSopenharmony_ci continue; 17463d58139fSopenharmony_ci } 17473d58139fSopenharmony_ci /* Now suppress is not set */ 17483d58139fSopenharmony_ci if (spec->arrayWidth == 0) { 17493d58139fSopenharmony_ci errNoMem = 1; /* We have exhausted the user's buffer */ 17503d58139fSopenharmony_ci break; 17513d58139fSopenharmony_ci } 17523d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 17533d58139fSopenharmony_ci errNoMem = SecInputForWchar(spec); 17543d58139fSopenharmony_ci#else 17553d58139fSopenharmony_ci errNoMem = SecInputForChar(spec, stream); 17563d58139fSopenharmony_ci#endif 17573d58139fSopenharmony_ci if (errNoMem != 0) { 17583d58139fSopenharmony_ci break; 17593d58139fSopenharmony_ci } 17603d58139fSopenharmony_ci } else { 17613d58139fSopenharmony_ci SecUnGetChar(spec->ch, stream, &(spec->charCount)); 17623d58139fSopenharmony_ci break; 17633d58139fSopenharmony_ci } 17643d58139fSopenharmony_ci } 17653d58139fSopenharmony_ci 17663d58139fSopenharmony_ci if (errNoMem != 0) { 17673d58139fSopenharmony_ci /* In case of error, blank out the input buffer */ 17683d58139fSopenharmony_ci SecAddEndingZero(startPtr, spec); 17693d58139fSopenharmony_ci return -1; 17703d58139fSopenharmony_ci } 17713d58139fSopenharmony_ci if ((spec->suppress != 0 && suppressed == 0) || 17723d58139fSopenharmony_ci (spec->suppress == 0 && startPtr == spec->argPtr)) { 17733d58139fSopenharmony_ci /* No input was scanned */ 17743d58139fSopenharmony_ci return -1; 17753d58139fSopenharmony_ci } 17763d58139fSopenharmony_ci if (spec->convChr != 'c') { 17773d58139fSopenharmony_ci /* Add null-terminate for strings */ 17783d58139fSopenharmony_ci SecAddEndingZero(spec->argPtr, spec); 17793d58139fSopenharmony_ci } 17803d58139fSopenharmony_ci if (spec->suppress == 0) { 17813d58139fSopenharmony_ci *doneCount = *doneCount + 1; 17823d58139fSopenharmony_ci } 17833d58139fSopenharmony_ci return 0; 17843d58139fSopenharmony_ci} 17853d58139fSopenharmony_ci 17863d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 17873d58139fSopenharmony_ci/* 17883d58139fSopenharmony_ci * Allocate buffer for wchar version of %[. 17893d58139fSopenharmony_ci * Return 0 OK 17903d58139fSopenharmony_ci */ 17913d58139fSopenharmony_ciSECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable) 17923d58139fSopenharmony_ci{ 17933d58139fSopenharmony_ci if (bracketTable->table == NULL) { 17943d58139fSopenharmony_ci /* Table should be freed after use */ 17953d58139fSopenharmony_ci bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE); 17963d58139fSopenharmony_ci if (bracketTable->table == NULL) { 17973d58139fSopenharmony_ci return -1; 17983d58139fSopenharmony_ci } 17993d58139fSopenharmony_ci } 18003d58139fSopenharmony_ci return 0; 18013d58139fSopenharmony_ci} 18023d58139fSopenharmony_ci 18033d58139fSopenharmony_ci/* 18043d58139fSopenharmony_ci * Free buffer for wchar version of %[ 18053d58139fSopenharmony_ci */ 18063d58139fSopenharmony_ciSECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable) 18073d58139fSopenharmony_ci{ 18083d58139fSopenharmony_ci if (bracketTable->table != NULL) { 18093d58139fSopenharmony_ci SECUREC_FREE(bracketTable->table); 18103d58139fSopenharmony_ci bracketTable->table = NULL; 18113d58139fSopenharmony_ci } 18123d58139fSopenharmony_ci} 18133d58139fSopenharmony_ci#endif 18143d58139fSopenharmony_ci 18153d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 18163d58139fSopenharmony_ci/* 18173d58139fSopenharmony_ci * Formatting input core functions for wchar version.Called by a function such as vswscanf_s 18183d58139fSopenharmony_ci */ 18193d58139fSopenharmony_ciint SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList) 18203d58139fSopenharmony_ci#else 18213d58139fSopenharmony_ci/* 18223d58139fSopenharmony_ci * Formatting input core functions for char version.Called by a function such as vsscanf_s 18233d58139fSopenharmony_ci */ 18243d58139fSopenharmony_ciint SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) 18253d58139fSopenharmony_ci#endif 18263d58139fSopenharmony_ci{ 18273d58139fSopenharmony_ci const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat; 18283d58139fSopenharmony_ci SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE; 18293d58139fSopenharmony_ci SecScanSpec spec; 18303d58139fSopenharmony_ci int doneCount = 0; 18313d58139fSopenharmony_ci int formatError = 0; 18323d58139fSopenharmony_ci int paraIsNull = 0; 18333d58139fSopenharmony_ci int match = 0; /* When % is found , inc this value */ 18343d58139fSopenharmony_ci int errRet = 0; 18353d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT 18363d58139fSopenharmony_ci SecFloatSpec floatSpec; 18373d58139fSopenharmony_ci SecInitFloatSpec(&floatSpec); 18383d58139fSopenharmony_ci#endif 18393d58139fSopenharmony_ci spec.ch = 0; /* Need to initialize to 0 */ 18403d58139fSopenharmony_ci spec.charCount = 0; /* Need to initialize to 0 */ 18413d58139fSopenharmony_ci 18423d58139fSopenharmony_ci /* Format must not NULL, use err < 1 to clear 845 */ 18433d58139fSopenharmony_ci while (errRet < 1 && *format != SECUREC_CHAR('\0')) { 18443d58139fSopenharmony_ci /* Skip space in format and space in input */ 18453d58139fSopenharmony_ci if (SecIsSpace((SecInt)(int)(*format)) != 0) { 18463d58139fSopenharmony_ci /* Read first no space char */ 18473d58139fSopenharmony_ci spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); 18483d58139fSopenharmony_ci /* Read the EOF cannot be returned directly here, because the case of " %n" needs to be handled */ 18493d58139fSopenharmony_ci /* Put fist no space char backup. put EOF back is also OK, and to modify the character count */ 18503d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 18513d58139fSopenharmony_ci SecSkipSpaceFormat(&format); 18523d58139fSopenharmony_ci continue; 18533d58139fSopenharmony_ci } 18543d58139fSopenharmony_ci 18553d58139fSopenharmony_ci if (*format != SECUREC_CHAR('%')) { 18563d58139fSopenharmony_ci spec.ch = SecGetChar(stream, &(spec.charCount)); 18573d58139fSopenharmony_ci if ((int)(*format) != (int)(spec.ch)) { 18583d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 18593d58139fSopenharmony_ci break; 18603d58139fSopenharmony_ci } 18613d58139fSopenharmony_ci ++format; 18623d58139fSopenharmony_ci#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) 18633d58139fSopenharmony_ci if (SecFilterWcharInFormat(&spec, &format, stream) != 0) { 18643d58139fSopenharmony_ci break; 18653d58139fSopenharmony_ci } 18663d58139fSopenharmony_ci#endif 18673d58139fSopenharmony_ci continue; 18683d58139fSopenharmony_ci } 18693d58139fSopenharmony_ci 18703d58139fSopenharmony_ci /* Now *format is % */ 18713d58139fSopenharmony_ci /* Set default value for each % */ 18723d58139fSopenharmony_ci SecSetDefaultScanSpec(&spec); 18733d58139fSopenharmony_ci if (SecDecodeScanFlag(&format, &spec) != 0) { 18743d58139fSopenharmony_ci formatError = 1; 18753d58139fSopenharmony_ci ++errRet; 18763d58139fSopenharmony_ci continue; 18773d58139fSopenharmony_ci } 18783d58139fSopenharmony_ci if (!SECUREC_FILED_WIDTH_ENOUGH(&spec)) { 18793d58139fSopenharmony_ci /* 0 width in format */ 18803d58139fSopenharmony_ci ++errRet; 18813d58139fSopenharmony_ci continue; 18823d58139fSopenharmony_ci } 18833d58139fSopenharmony_ci 18843d58139fSopenharmony_ci /* Update wchar flag for %S %C */ 18853d58139fSopenharmony_ci SecUpdateWcharFlagByType(*format, &spec); 18863d58139fSopenharmony_ci 18873d58139fSopenharmony_ci spec.convChr = SECUREC_TO_LOWERCASE(*format); 18883d58139fSopenharmony_ci spec.oriConvChr = spec.convChr; /* convChr may be modified to handle integer logic */ 18893d58139fSopenharmony_ci if (spec.convChr != 'n') { 18903d58139fSopenharmony_ci if (spec.convChr != 'c' && spec.convChr != SECUREC_BRACE) { 18913d58139fSopenharmony_ci spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); 18923d58139fSopenharmony_ci } else { 18933d58139fSopenharmony_ci spec.ch = SecGetChar(stream, &(spec.charCount)); 18943d58139fSopenharmony_ci } 18953d58139fSopenharmony_ci if (spec.ch == SECUREC_EOF) { 18963d58139fSopenharmony_ci ++errRet; 18973d58139fSopenharmony_ci continue; 18983d58139fSopenharmony_ci } 18993d58139fSopenharmony_ci } 19003d58139fSopenharmony_ci 19013d58139fSopenharmony_ci /* Now no 0 width in format and get one char from input */ 19023d58139fSopenharmony_ci switch (spec.oriConvChr) { 19033d58139fSopenharmony_ci case 'c': /* Also 'C' */ 19043d58139fSopenharmony_ci if (spec.widthSet == 0) { 19053d58139fSopenharmony_ci spec.widthSet = 1; 19063d58139fSopenharmony_ci spec.width = 1; 19073d58139fSopenharmony_ci } 19083d58139fSopenharmony_ci /* fall-through */ /* FALLTHRU */ 19093d58139fSopenharmony_ci case 's': /* Also 'S': */ 19103d58139fSopenharmony_ci /* fall-through */ /* FALLTHRU */ 19113d58139fSopenharmony_ci case SECUREC_BRACE: 19123d58139fSopenharmony_ci /* Unset last char to stream */ 19133d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 19143d58139fSopenharmony_ci /* Check dest buffer and size */ 19153d58139fSopenharmony_ci if (spec.suppress == 0) { 19163d58139fSopenharmony_ci spec.argPtr = (void *)va_arg(argList, void *); 19173d58139fSopenharmony_ci if (spec.argPtr == NULL) { 19183d58139fSopenharmony_ci paraIsNull = 1; 19193d58139fSopenharmony_ci ++errRet; 19203d58139fSopenharmony_ci continue; 19213d58139fSopenharmony_ci } 19223d58139fSopenharmony_ci /* Get the next argument, size of the array in characters */ 19233d58139fSopenharmony_ci spec.arrayWidth = SECUREC_GET_ARRAYWIDTH(argList); 19243d58139fSopenharmony_ci if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) { 19253d58139fSopenharmony_ci /* Do not clear buffer just go error */ 19263d58139fSopenharmony_ci ++errRet; 19273d58139fSopenharmony_ci continue; 19283d58139fSopenharmony_ci } 19293d58139fSopenharmony_ci /* One element is needed for '\0' for %s and %[ */ 19303d58139fSopenharmony_ci if (spec.convChr != 'c') { 19313d58139fSopenharmony_ci --spec.arrayWidth; 19323d58139fSopenharmony_ci } 19333d58139fSopenharmony_ci } else { 19343d58139fSopenharmony_ci /* Set argPtr to NULL is necessary, in suppress mode we don't use argPtr to store data */ 19353d58139fSopenharmony_ci spec.argPtr = NULL; 19363d58139fSopenharmony_ci } 19373d58139fSopenharmony_ci 19383d58139fSopenharmony_ci if (spec.convChr == SECUREC_BRACE) { 19393d58139fSopenharmony_ci /* Malloc when first %[ is meet for wchar version */ 19403d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 19413d58139fSopenharmony_ci if (SecAllocBracketTable(&bracketTable) != 0) { 19423d58139fSopenharmony_ci ++errRet; 19433d58139fSopenharmony_ci continue; 19443d58139fSopenharmony_ci } 19453d58139fSopenharmony_ci#endif 19463d58139fSopenharmony_ci (void)SECUREC_MEMSET_FUNC_OPT(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE); 19473d58139fSopenharmony_ci if (SecSetupBracketTable(&format, &bracketTable) != 0) { 19483d58139fSopenharmony_ci ++errRet; 19493d58139fSopenharmony_ci continue; 19503d58139fSopenharmony_ci } 19513d58139fSopenharmony_ci 19523d58139fSopenharmony_ci if (*format == SECUREC_CHAR('\0')) { 19533d58139fSopenharmony_ci /* Default add string terminator */ 19543d58139fSopenharmony_ci SecAddEndingZero(spec.argPtr, &spec); 19553d58139fSopenharmony_ci ++errRet; 19563d58139fSopenharmony_ci /* Truncated format */ 19573d58139fSopenharmony_ci continue; 19583d58139fSopenharmony_ci } 19593d58139fSopenharmony_ci } 19603d58139fSopenharmony_ci 19613d58139fSopenharmony_ci /* Set completed. Now read string or character */ 19623d58139fSopenharmony_ci if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) { 19633d58139fSopenharmony_ci ++errRet; 19643d58139fSopenharmony_ci continue; 19653d58139fSopenharmony_ci } 19663d58139fSopenharmony_ci break; 19673d58139fSopenharmony_ci case 'p': 19683d58139fSopenharmony_ci /* Make %hp same as %p */ 19693d58139fSopenharmony_ci spec.numberWidth = SECUREC_NUM_WIDTH_INT; 19703d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS 19713d58139fSopenharmony_ci spec.numberArgType = 1; 19723d58139fSopenharmony_ci#endif 19733d58139fSopenharmony_ci /* fall-through */ /* FALLTHRU */ 19743d58139fSopenharmony_ci case 'o': /* fall-through */ /* FALLTHRU */ 19753d58139fSopenharmony_ci case 'u': /* fall-through */ /* FALLTHRU */ 19763d58139fSopenharmony_ci case 'd': /* fall-through */ /* FALLTHRU */ 19773d58139fSopenharmony_ci case 'i': /* fall-through */ /* FALLTHRU */ 19783d58139fSopenharmony_ci case 'x': 19793d58139fSopenharmony_ci /* Unset last char to stream */ 19803d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 19813d58139fSopenharmony_ci if (SecInputNumber(stream, &spec) != 0) { 19823d58139fSopenharmony_ci ++errRet; 19833d58139fSopenharmony_ci continue; 19843d58139fSopenharmony_ci } 19853d58139fSopenharmony_ci if (spec.suppress == 0) { 19863d58139fSopenharmony_ci spec.argPtr = (void *)va_arg(argList, void *); 19873d58139fSopenharmony_ci if (spec.argPtr == NULL) { 19883d58139fSopenharmony_ci paraIsNull = 1; 19893d58139fSopenharmony_ci ++errRet; 19903d58139fSopenharmony_ci continue; 19913d58139fSopenharmony_ci } 19923d58139fSopenharmony_ci SecAssignNumber(&spec); 19933d58139fSopenharmony_ci ++doneCount; 19943d58139fSopenharmony_ci } 19953d58139fSopenharmony_ci break; 19963d58139fSopenharmony_ci case 'n': /* Char count */ 19973d58139fSopenharmony_ci if (spec.suppress == 0) { 19983d58139fSopenharmony_ci spec.argPtr = (void *)va_arg(argList, void *); 19993d58139fSopenharmony_ci if (spec.argPtr == NULL) { 20003d58139fSopenharmony_ci paraIsNull = 1; 20013d58139fSopenharmony_ci ++errRet; 20023d58139fSopenharmony_ci continue; 20033d58139fSopenharmony_ci } 20043d58139fSopenharmony_ci spec.number = (unsigned long)(unsigned int)(spec.charCount); 20053d58139fSopenharmony_ci spec.numberArgType = 0; 20063d58139fSopenharmony_ci SecAssignNumber(&spec); 20073d58139fSopenharmony_ci } 20083d58139fSopenharmony_ci break; 20093d58139fSopenharmony_ci case 'e': /* fall-through */ /* FALLTHRU */ 20103d58139fSopenharmony_ci case 'f': /* fall-through */ /* FALLTHRU */ 20113d58139fSopenharmony_ci case 'g': /* Scan a float */ 20123d58139fSopenharmony_ci /* Unset last char to stream */ 20133d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 20143d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT 20153d58139fSopenharmony_ci if (SecInputFloat(stream, &spec, &floatSpec) != 0) { 20163d58139fSopenharmony_ci ++errRet; 20173d58139fSopenharmony_ci continue; 20183d58139fSopenharmony_ci } 20193d58139fSopenharmony_ci if (spec.suppress == 0) { 20203d58139fSopenharmony_ci spec.argPtr = (void *)va_arg(argList, void *); 20213d58139fSopenharmony_ci if (spec.argPtr == NULL) { 20223d58139fSopenharmony_ci ++errRet; 20233d58139fSopenharmony_ci paraIsNull = 1; 20243d58139fSopenharmony_ci continue; 20253d58139fSopenharmony_ci } 20263d58139fSopenharmony_ci if (SecAssignFloat(&floatSpec, &spec) != 0) { 20273d58139fSopenharmony_ci ++errRet; 20283d58139fSopenharmony_ci continue; 20293d58139fSopenharmony_ci } 20303d58139fSopenharmony_ci ++doneCount; 20313d58139fSopenharmony_ci } 20323d58139fSopenharmony_ci break; 20333d58139fSopenharmony_ci#else /* SECUREC_ENABLE_SCANF_FLOAT */ 20343d58139fSopenharmony_ci ++errRet; 20353d58139fSopenharmony_ci continue; 20363d58139fSopenharmony_ci#endif 20373d58139fSopenharmony_ci default: 20383d58139fSopenharmony_ci if ((int)(*format) != (int)spec.ch) { 20393d58139fSopenharmony_ci SecUnGetChar(spec.ch, stream, &(spec.charCount)); 20403d58139fSopenharmony_ci formatError = 1; 20413d58139fSopenharmony_ci ++errRet; 20423d58139fSopenharmony_ci continue; 20433d58139fSopenharmony_ci } else { 20443d58139fSopenharmony_ci --match; /* Compensate for the self-increment of the following code */ 20453d58139fSopenharmony_ci } 20463d58139fSopenharmony_ci break; 20473d58139fSopenharmony_ci } 20483d58139fSopenharmony_ci ++match; 20493d58139fSopenharmony_ci ++format; 20503d58139fSopenharmony_ci } 20513d58139fSopenharmony_ci 20523d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 20533d58139fSopenharmony_ci SecFreeBracketTable(&bracketTable); 20543d58139fSopenharmony_ci#endif 20553d58139fSopenharmony_ci 20563d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT 20573d58139fSopenharmony_ci SecFreeFloatSpec(&floatSpec, &doneCount); 20583d58139fSopenharmony_ci#endif 20593d58139fSopenharmony_ci 20603d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE 20613d58139fSopenharmony_ci SecAdjustStream(stream); 20623d58139fSopenharmony_ci#endif 20633d58139fSopenharmony_ci 20643d58139fSopenharmony_ci if (spec.ch == SECUREC_EOF) { 20653d58139fSopenharmony_ci return ((doneCount != 0 || match != 0) ? doneCount : SECUREC_SCANF_EINVAL); 20663d58139fSopenharmony_ci } 20673d58139fSopenharmony_ci if (formatError != 0 || paraIsNull != 0) { 20683d58139fSopenharmony_ci /* Invalid Input Format or parameter, but not meet EOF */ 20693d58139fSopenharmony_ci return SECUREC_SCANF_ERROR_PARA; 20703d58139fSopenharmony_ci } 20713d58139fSopenharmony_ci return doneCount; 20723d58139fSopenharmony_ci} 20733d58139fSopenharmony_ci 20743d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE 20753d58139fSopenharmony_ci/* 20763d58139fSopenharmony_ci * Get char from stream use std function 20773d58139fSopenharmony_ci */ 20783d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream) 20793d58139fSopenharmony_ci{ 20803d58139fSopenharmony_ci SecInt ch; 20813d58139fSopenharmony_ci ch = SECUREC_GETC(stream->pf); 20823d58139fSopenharmony_ci return ch; 20833d58139fSopenharmony_ci} 20843d58139fSopenharmony_ci 20853d58139fSopenharmony_ci/* 20863d58139fSopenharmony_ci * Try to read the BOM header, when meet a BOM head, discard it, then data is Aligned to base 20873d58139fSopenharmony_ci */ 20883d58139fSopenharmony_ciSECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream) 20893d58139fSopenharmony_ci{ 20903d58139fSopenharmony_ci /* Use size_t type conversion to clean e747 */ 20913d58139fSopenharmony_ci stream->count = fread(stream->base, (size_t)1, (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf); 20923d58139fSopenharmony_ci if (stream->count > SECUREC_BOM_HEADER_SIZE) { 20933d58139fSopenharmony_ci stream->count = 0; 20943d58139fSopenharmony_ci } 20953d58139fSopenharmony_ci if (SECUREC_BEGIN_WITH_BOM(stream->base, stream->count)) { 20963d58139fSopenharmony_ci /* It's BOM header, discard it */ 20973d58139fSopenharmony_ci stream->count = 0; 20983d58139fSopenharmony_ci } 20993d58139fSopenharmony_ci} 21003d58139fSopenharmony_ci 21013d58139fSopenharmony_ci/* 21023d58139fSopenharmony_ci * Get char from file stream or buffer 21033d58139fSopenharmony_ci */ 21043d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream) 21053d58139fSopenharmony_ci{ 21063d58139fSopenharmony_ci SecInt ch; 21073d58139fSopenharmony_ci if (stream->count < sizeof(SecChar)) { 21083d58139fSopenharmony_ci /* Load file to buffer */ 21093d58139fSopenharmony_ci size_t len; 21103d58139fSopenharmony_ci if (stream->base != NULL) { 21113d58139fSopenharmony_ci /* Put the last unread data in the buffer head */ 21123d58139fSopenharmony_ci for (len = 0; len < stream->count; ++len) { 21133d58139fSopenharmony_ci stream->base[len] = stream->cur[len]; 21143d58139fSopenharmony_ci } 21153d58139fSopenharmony_ci } else { 21163d58139fSopenharmony_ci stream->oriFilePos = ftell(stream->pf); /* Save original file read position */ 21173d58139fSopenharmony_ci if (stream->oriFilePos == -1) { 21183d58139fSopenharmony_ci /* It may be a pipe stream */ 21193d58139fSopenharmony_ci stream->flag = SECUREC_PIPE_STREAM_FLAG; 21203d58139fSopenharmony_ci return SecGetCharFromStream(stream); 21213d58139fSopenharmony_ci } 21223d58139fSopenharmony_ci /* Reserve the length of BOM head */ 21233d58139fSopenharmony_ci stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + 21243d58139fSopenharmony_ci SECUREC_BOM_HEADER_SIZE + sizeof(SecChar)); /* To store '\0' and aligned to wide char */ 21253d58139fSopenharmony_ci if (stream->base == NULL) { 21263d58139fSopenharmony_ci return SECUREC_EOF; 21273d58139fSopenharmony_ci } 21283d58139fSopenharmony_ci /* First read file */ 21293d58139fSopenharmony_ci if (stream->oriFilePos == 0) { 21303d58139fSopenharmony_ci /* Make sure the data is aligned to base */ 21313d58139fSopenharmony_ci SecReadAndSkipBomHeader(stream); 21323d58139fSopenharmony_ci } 21333d58139fSopenharmony_ci } 21343d58139fSopenharmony_ci 21353d58139fSopenharmony_ci /* Skip existing data and read data */ 21363d58139fSopenharmony_ci len = fread(stream->base + stream->count, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf); 21373d58139fSopenharmony_ci if (len > SECUREC_BUFFERED_BLOK_SIZE) { /* It won't happen, */ 21383d58139fSopenharmony_ci len = 0; 21393d58139fSopenharmony_ci } 21403d58139fSopenharmony_ci stream->count += len; 21413d58139fSopenharmony_ci stream->cur = stream->base; 21423d58139fSopenharmony_ci stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG; 21433d58139fSopenharmony_ci stream->base[stream->count] = '\0'; /* For tool Warning string null */ 21443d58139fSopenharmony_ci } 21453d58139fSopenharmony_ci 21463d58139fSopenharmony_ci SECUREC_GET_CHAR(stream, &ch); 21473d58139fSopenharmony_ci if (ch != SECUREC_EOF) { 21483d58139fSopenharmony_ci stream->fileRealRead += sizeof(SecChar); 21493d58139fSopenharmony_ci } 21503d58139fSopenharmony_ci return ch; 21513d58139fSopenharmony_ci} 21523d58139fSopenharmony_ci#endif 21533d58139fSopenharmony_ci 21543d58139fSopenharmony_ci/* 21553d58139fSopenharmony_ci * Get char for wchar version 21563d58139fSopenharmony_ci */ 21573d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter) 21583d58139fSopenharmony_ci{ 21593d58139fSopenharmony_ci *counter = *counter + 1; /* Always plus 1 */ 21603d58139fSopenharmony_ci /* The main scenario is scanf str */ 21613d58139fSopenharmony_ci if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) { 21623d58139fSopenharmony_ci SecInt ch; 21633d58139fSopenharmony_ci SECUREC_GET_CHAR(stream, &ch); 21643d58139fSopenharmony_ci return ch; 21653d58139fSopenharmony_ci } 21663d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE 21673d58139fSopenharmony_ci if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0) { 21683d58139fSopenharmony_ci return SecGetCharFromFile(stream); 21693d58139fSopenharmony_ci } 21703d58139fSopenharmony_ci if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) { 21713d58139fSopenharmony_ci return SecGetCharFromStream(stream); 21723d58139fSopenharmony_ci } 21733d58139fSopenharmony_ci#endif 21743d58139fSopenharmony_ci return SECUREC_EOF; 21753d58139fSopenharmony_ci} 21763d58139fSopenharmony_ci 21773d58139fSopenharmony_ci/* 21783d58139fSopenharmony_ci * Unget Public realization char for wchar and char version 21793d58139fSopenharmony_ci */ 21803d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream) 21813d58139fSopenharmony_ci{ 21823d58139fSopenharmony_ci if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) { 21833d58139fSopenharmony_ci SECUREC_UN_GET_CHAR(stream); 21843d58139fSopenharmony_ci return; 21853d58139fSopenharmony_ci } 21863d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE 21873d58139fSopenharmony_ci if ((stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) != 0) { 21883d58139fSopenharmony_ci SECUREC_UN_GET_CHAR(stream); 21893d58139fSopenharmony_ci if (stream->fileRealRead > 0) { 21903d58139fSopenharmony_ci stream->fileRealRead -= sizeof(SecChar); 21913d58139fSopenharmony_ci } 21923d58139fSopenharmony_ci return; 21933d58139fSopenharmony_ci } 21943d58139fSopenharmony_ci if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) { 21953d58139fSopenharmony_ci (void)SECUREC_UN_GETC(ch, stream->pf); 21963d58139fSopenharmony_ci return; 21973d58139fSopenharmony_ci } 21983d58139fSopenharmony_ci#else 21993d58139fSopenharmony_ci (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 22003d58139fSopenharmony_ci#endif 22013d58139fSopenharmony_ci} 22023d58139fSopenharmony_ci 22033d58139fSopenharmony_ci/* 22043d58139fSopenharmony_ci * Unget char for char version 22053d58139fSopenharmony_ci */ 22063d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter) 22073d58139fSopenharmony_ci{ 22083d58139fSopenharmony_ci *counter = *counter - 1; /* Always minus 1 */ 22093d58139fSopenharmony_ci if (ch != SECUREC_EOF) { 22103d58139fSopenharmony_ci SecUnGetCharImpl(ch, stream); 22113d58139fSopenharmony_ci } 22123d58139fSopenharmony_ci} 22133d58139fSopenharmony_ci 22143d58139fSopenharmony_ci/* 22153d58139fSopenharmony_ci * Skip space char by isspace 22163d58139fSopenharmony_ci */ 22173d58139fSopenharmony_ciSECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter) 22183d58139fSopenharmony_ci{ 22193d58139fSopenharmony_ci SecInt ch; 22203d58139fSopenharmony_ci do { 22213d58139fSopenharmony_ci ch = SecGetChar(stream, counter); 22223d58139fSopenharmony_ci if (ch == SECUREC_EOF) { 22233d58139fSopenharmony_ci break; 22243d58139fSopenharmony_ci } 22253d58139fSopenharmony_ci } while (SecIsSpace(ch) != 0); 22263d58139fSopenharmony_ci return ch; 22273d58139fSopenharmony_ci} 22283d58139fSopenharmony_ci#endif /* INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 */ 22293d58139fSopenharmony_ci 2230