1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved. 3 * Licensed under Mulan PSL v2. 4 * You can use this software according to the terms and conditions of the Mulan PSL v2. 5 * You may obtain a copy of Mulan PSL v2 at: 6 * http://license.coscl.org.cn/MulanPSL2 7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 10 * See the Mulan PSL v2 for more details. 11 * Description: Used by secureinput_a.c and secureinput_w.c to include. 12 * This file provides a template function for ANSI and UNICODE compiling by 13 * different type definition. The functions of SecInputS or 14 * SecInputSW provides internal implementation for scanf family API, such as sscanf_s, fscanf_s. 15 * Create: 2014-02-25 16 * Notes: The formatted input processing results of integers on different platforms are different. 17 */ 18/* 19 * [Standardize-exceptions] Use unsafe function: Performance-sensitive 20 * [reason] Always used in the performance critical path, 21 * and sufficient input validation is performed before calling 22 */ 23#ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 24#define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 25 26#if SECUREC_IN_KERNEL 27#if !defined(SECUREC_CTYPE_MACRO_ADAPT) 28#include <linux/ctype.h> 29#endif 30#else 31#if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT) 32#include <ctype.h> 33#ifdef SECUREC_FOR_WCHAR 34#include <wctype.h> /* For iswspace */ 35#endif 36#endif 37#endif 38 39#ifndef EOF 40#define EOF (-1) 41#endif 42 43#define SECUREC_NUM_WIDTH_SHORT 0 44#define SECUREC_NUM_WIDTH_INT 1 45#define SECUREC_NUM_WIDTH_LONG 2 46#define SECUREC_NUM_WIDTH_LONG_LONG 3 /* Also long double */ 47 48#define SECUREC_BUFFERED_BLOK_SIZE 1024U 49 50#if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy) 51/* The name is the same as system macro. */ 52#define __va_copy(dest, src) do { \ 53 size_t destSize_ = (size_t)sizeof(dest); \ 54 size_t srcSize_ = (size_t)sizeof(src); \ 55 if (destSize_ != srcSize_) { \ 56 SECUREC_MEMCPY_WARP_OPT((dest), (src), sizeof(va_list)); \ 57 } else { \ 58 SECUREC_MEMCPY_WARP_OPT(&(dest), &(src), sizeof(va_list)); \ 59 } \ 60} SECUREC_WHILE_ZERO 61#endif 62 63#define SECUREC_MULTI_BYTE_MAX_LEN 6 64 65/* Compatibility macro name cannot be modifie */ 66#ifndef UNALIGNED 67#if !(defined(_M_IA64)) && !(defined(_M_AMD64)) 68#define UNALIGNED 69#else 70#define UNALIGNED __unaligned 71#endif 72#endif 73 74#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 75/* Max 64bit value is 0xffffffffffffffff */ 76#define SECUREC_MAX_64BITS_VALUE 18446744073709551615ULL 77#define SECUREC_MAX_64BITS_VALUE_DIV_TEN 1844674407370955161ULL 78#define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL 79#define SECUREC_MIN_64BITS_NEG_VALUE 9223372036854775808ULL 80#define SECUREC_MAX_64BITS_POS_VALUE 9223372036854775807ULL 81#define SECUREC_MIN_32BITS_NEG_VALUE 2147483648UL 82#define SECUREC_MAX_32BITS_POS_VALUE 2147483647UL 83#define SECUREC_MAX_32BITS_VALUE 4294967295UL 84#define SECUREC_MAX_32BITS_VALUE_INC 4294967296UL 85#define SECUREC_MAX_32BITS_VALUE_DIV_TEN 429496729UL 86#define SECUREC_LONG_BIT_NUM ((unsigned int)(sizeof(long) << 3U)) 87/* Use ULL to clean up cl6x compilation alerts */ 88#define SECUREC_MAX_LONG_POS_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1) 89#define SECUREC_MIN_LONG_NEG_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1))) 90 91/* Covert to long long to clean up cl6x compilation alerts */ 92#define SECUREC_LONG_HEX_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0) 93#define SECUREC_LONG_OCTAL_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0) 94 95#define SECUREC_QWORD_HEX_BEYOND_MAX(number) (((number) >> (64U - 4U)) > 0) 96#define SECUREC_QWORD_OCTAL_BEYOND_MAX(number) (((number) >> (64U - 3U)) > 0) 97 98#define SECUREC_LP64_BIT_WIDTH 64 99#define SECUREC_LP32_BIT_WIDTH 32 100 101#define SECUREC_CONVERT_IS_SIGNED(conv) ((conv) == 'd' || (conv) == 'i') 102#endif 103 104#define SECUREC_BRACE '{' /* [ to { */ 105#define SECUREC_FILED_WIDTH_ENOUGH(spec) ((spec)->widthSet == 0 || (spec)->width > 0) 106#define SECUREC_FILED_WIDTH_DEC(spec) do { \ 107 if ((spec)->widthSet != 0) { \ 108 --(spec)->width; \ 109 } \ 110} SECUREC_WHILE_ZERO 111 112#ifdef SECUREC_FOR_WCHAR 113/* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */ 114#define SECUREC_BRACKET_TABLE_SIZE 8192 115#define SECUREC_EOF WEOF 116#define SECUREC_MB_LEN 16 /* Max. # bytes in multibyte char ,see MB_LEN_MAX */ 117#else 118/* Bits for all char, size is 256/8 */ 119#define SECUREC_BRACKET_TABLE_SIZE 32 120#define SECUREC_EOF EOF 121#endif 122 123#if SECUREC_HAVE_WCHART 124#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \ 125 ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \ 126 ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN)) 127#else 128#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || (spec).arrayWidth > SECUREC_STRING_MAX_LEN) 129#endif 130 131#ifdef SECUREC_ON_64BITS 132/* Use 0xffffffffUL mask to pass integer as array length */ 133#define SECUREC_GET_ARRAYWIDTH(argList) (((size_t)va_arg((argList), size_t)) & 0xffffffffUL) 134#else /* !SECUREC_ON_64BITS */ 135#define SECUREC_GET_ARRAYWIDTH(argList) ((size_t)va_arg((argList), size_t)) 136#endif 137 138typedef struct { 139#ifdef SECUREC_FOR_WCHAR 140 unsigned char *table; /* Default NULL */ 141#else 142 unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */ 143#endif 144 unsigned char mask; /* Default 0 */ 145} SecBracketTable; 146 147#ifdef SECUREC_FOR_WCHAR 148#define SECUREC_INIT_BRACKET_TABLE { NULL, 0 } 149#else 150#define SECUREC_INIT_BRACKET_TABLE { {0}, 0 } 151#endif 152 153#if SECUREC_ENABLE_SCANF_FLOAT 154typedef struct { 155 size_t floatStrTotalLen; /* Initialization must be length of buffer in charater */ 156 size_t floatStrUsedLen; /* Store float string len */ 157 SecChar *floatStr; /* Initialization must point to buffer */ 158 SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */ 159 SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1]; 160} SecFloatSpec; 161#endif 162 163#define SECUREC_NUMBER_STATE_DEFAULT 0U 164#define SECUREC_NUMBER_STATE_STARTED 1U 165 166typedef struct { 167 SecInt ch; /* Char read from input */ 168 int charCount; /* Number of characters processed */ 169 void *argPtr; /* Variable parameter pointer, point to the end of the string */ 170 size_t arrayWidth; /* Length of pointer Variable parameter, in charaters */ 171 SecUnsignedInt64 number64; /* Store input number64 value */ 172 unsigned long number; /* Store input number32 value */ 173 int numberWidth; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ 174 int numberArgType; /* 1 for 64-bit integer, 0 otherwise. use it as decode function index */ 175 unsigned int negative; /* 0 is positive */ 176#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 177 unsigned int beyondMax; /* Non-zero means beyond */ 178#endif 179 unsigned int numberState; /* Identifies whether to start processing numbers, 1 is can input number */ 180 int width; /* Width number in format */ 181 int widthSet; /* 0 is not set width in format */ 182 int convChr; /* Lowercase format conversion characters */ 183 int oriConvChr; /* Store original format conversion, convChr may change when parsing integers */ 184 signed char isWCharOrLong; /* -1/0 not wchar or long, 1 for wchar or long */ 185 unsigned char suppress; /* 0 is not have %* in format */ 186} SecScanSpec; 187 188#ifdef SECUREC_FOR_WCHAR 189#define SECUREC_GETC fgetwc 190#define SECUREC_UN_GETC ungetwc 191/* Only supports wide characters with a maximum length of two bytes in format string */ 192#define SECUREC_BRACKET_CHAR_MASK 0xffffU 193#else 194#define SECUREC_GETC fgetc 195#define SECUREC_UN_GETC ungetc 196#define SECUREC_BRACKET_CHAR_MASK 0xffU 197#endif 198 199#define SECUREC_CHAR_SIZE ((unsigned int)(sizeof(SecChar))) 200/* To avoid 648, mask high bit: 0x00ffffff 0x0000ffff or 0x00000000 */ 201#define SECUREC_CHAR_MASK_HIGH (((((((((unsigned int)(-1) >> SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 202 SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 203 SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \ 204 SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) 205 206/* For char is 0xff, wcahr_t is 0xffff or 0xffffffff. */ 207#define SECUREC_CHAR_MASK (~((((((((((unsigned int)(-1) & SECUREC_CHAR_MASK_HIGH) << \ 208 SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 209 SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 210 SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \ 211 SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE)) 212 213/* According wchar_t has multiple bytes, so use sizeof */ 214#define SECUREC_GET_CHAR(stream, outCh) do { \ 215 if ((stream)->count >= sizeof(SecChar)) { \ 216 *(outCh) = (SecInt)(SECUREC_CHAR_MASK & \ 217 (unsigned int)(int)(*((const SecChar *)(const void *)(stream)->cur))); \ 218 (stream)->cur += sizeof(SecChar); \ 219 (stream)->count -= sizeof(SecChar); \ 220 } else { \ 221 *(outCh) = SECUREC_EOF; \ 222 } \ 223} SECUREC_WHILE_ZERO 224 225#define SECUREC_UN_GET_CHAR(stream) do { \ 226 if ((stream)->cur > (stream)->base) { \ 227 (stream)->cur -= sizeof(SecChar); \ 228 (stream)->count += sizeof(SecChar); \ 229 } \ 230} SECUREC_WHILE_ZERO 231 232/* Convert wchar_t to int and then to unsigned int to keep data clearing warning */ 233#define SECUREC_TO_LOWERCASE(chr) ((int)((unsigned int)(int)(chr) | (unsigned int)('a' - 'A'))) 234 235/* Record a flag for each bit */ 236#define SECUREC_BRACKET_INDEX(x) ((unsigned int)(x) >> 3U) 237#define SECUREC_BRACKET_VALUE(x) ((unsigned char)(1U << ((unsigned int)(x) & 7U))) 238#if SECUREC_IN_KERNEL 239#define SECUREC_CONVERT_IS_UNSIGNED(conv) ((conv) == 'x' || (conv) == 'o' || (conv) == 'u') 240#endif 241 242/* 243 * Set char in %[xxx] into table, only supports wide characters with a maximum length of two bytes 244 */ 245SECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch) 246{ 247 unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 248 unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 249 /* Do not use |= optimize this code, it will cause compiling warning */ 250 table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue); 251} 252 253SECUREC_INLINE void SecBracketSetBitRange(unsigned char *table, SecUnsignedChar startCh, SecUnsignedChar endCh) 254{ 255 SecUnsignedChar expCh; 256 /* %[a-z] %[a-a] Format %[a-\xff] end is 0xFF, condition (expCh <= endChar) cause dead loop */ 257 for (expCh = startCh; expCh < endCh; ++expCh) { 258 SecBracketSetBit(table, expCh); 259 } 260 SecBracketSetBit(table, endCh); 261} 262/* 263 * Determine whether the expression can be satisfied 264 */ 265SECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable) 266{ 267 unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 268 unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK)); 269#ifdef SECUREC_FOR_WCHAR 270 if (((unsigned int)(int)ch & (~(SECUREC_BRACKET_CHAR_MASK))) != 0) { 271 /* The value of the wide character exceeds the size of two bytes */ 272 return 0; 273 } 274 return (int)(convChr == SECUREC_BRACE && 275 (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0); 276#else 277 return (int)(convChr == SECUREC_BRACE && 278 (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0); 279#endif 280} 281 282/* 283 * String input ends when blank character is encountered 284 */ 285SECUREC_INLINE int SecCanInputString(int convChr, SecInt ch) 286{ 287 return (int)(convChr == 's' && 288 (!(ch >= SECUREC_CHAR('\t') && ch <= SECUREC_CHAR('\r')) && ch != SECUREC_CHAR(' '))); 289} 290 291/* 292 * Can input a character when format is %c 293 */ 294SECUREC_INLINE int SecCanInputCharacter(int convChr) 295{ 296 return (int)(convChr == 'c'); 297} 298 299/* 300 * Determine if it is a 64-bit pointer function 301 * Return 0 is not ,1 is 64bit pointer 302 */ 303SECUREC_INLINE int SecNumberArgType(size_t sizeOfVoidStar) 304{ 305 /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */ 306 /* To clear e778 */ 307 if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) { 308 return 1; 309 } 310 return 0; 311} 312SECUREC_INLINE int SecIsDigit(SecInt ch); 313SECUREC_INLINE int SecIsXdigit(SecInt ch); 314SECUREC_INLINE int SecIsSpace(SecInt ch); 315SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter); 316SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter); 317SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter); 318 319#if SECUREC_ENABLE_SCANF_FLOAT 320 321/* 322 * Convert a floating point string to a floating point number 323 */ 324SECUREC_INLINE int SecAssignNarrowFloat(const char *floatStr, const SecScanSpec *spec) 325{ 326 char *endPtr = NULL; 327 double d; 328#if SECUREC_SUPPORT_STRTOLD 329 if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) { 330 long double d2 = strtold(floatStr, &endPtr); 331 if (endPtr == floatStr) { 332 return -1; 333 } 334 *(long double UNALIGNED *)(spec->argPtr) = d2; 335 return 0; 336 } 337#endif 338 d = strtod(floatStr, &endPtr); 339 /* cannot detect if endPtr points to the end of floatStr,because strtod handles only two characters for 1.E */ 340 if (endPtr == floatStr) { 341 return -1; 342 } 343 if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) { 344 *(double UNALIGNED *)(spec->argPtr) = (double)d; 345 } else { 346 *(float UNALIGNED *)(spec->argPtr) = (float)d; 347 } 348 return 0; 349} 350 351#ifdef SECUREC_FOR_WCHAR 352/* 353 * Convert a floating point wchar string to a floating point number 354 * Success ret 0 355 */ 356SECUREC_INLINE int SecAssignWideFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec) 357{ 358 int retVal; 359 /* Convert float string */ 360 size_t mbsLen; 361 size_t tempFloatStrLen = (size_t)(floatSpec->floatStrUsedLen + 1) * sizeof(wchar_t); 362 char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen); 363 if (tempFloatStr == NULL) { 364 return -1; 365 } 366 tempFloatStr[0] = '\0'; 367 SECUREC_MASK_MSVC_CRT_WARNING 368 mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1); 369 SECUREC_END_MASK_MSVC_CRT_WARNING 370 /* This condition must satisfy mbsLen is not -1 */ 371 if (mbsLen >= tempFloatStrLen) { 372 SECUREC_FREE(tempFloatStr); 373 return -1; 374 } 375 tempFloatStr[mbsLen] = '\0'; 376 retVal = SecAssignNarrowFloat(tempFloatStr, spec); 377 SECUREC_FREE(tempFloatStr); 378 return retVal; 379} 380#endif 381 382SECUREC_INLINE int SecAssignFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec) 383{ 384#ifdef SECUREC_FOR_WCHAR 385 return SecAssignWideFloat(floatSpec, spec); 386#else 387 return SecAssignNarrowFloat(floatSpec->floatStr, spec); 388#endif 389} 390 391/* 392 * Init SecFloatSpec before parse format 393 */ 394SECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec) 395{ 396 floatSpec->floatStr = floatSpec->buffer; 397 floatSpec->allocatedFloatStr = NULL; 398 floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]); 399 floatSpec->floatStrUsedLen = 0; 400} 401 402SECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount) 403{ 404 /* 2014.3.6 add, clear the stack data */ 405 if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) { 406 *doneCount = 0; /* This code just to meet the coding requirements */ 407 } 408 /* The pFloatStr can be alloced in SecExtendFloatLen function, clear and free it */ 409 if (floatSpec->allocatedFloatStr != NULL) { 410 size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar); 411 if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) { 412 *doneCount = 0; /* This code just to meet the coding requirements */ 413 } 414 SECUREC_FREE(floatSpec->allocatedFloatStr); 415 floatSpec->allocatedFloatStr = NULL; 416 floatSpec->floatStr = NULL; 417 } 418} 419 420/* 421 * Splice floating point string 422 * Return 0 OK 423 */ 424SECUREC_INLINE int SecExtendFloatLen(SecFloatSpec *floatSpec) 425{ 426 if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) { 427 /* Buffer size is len x sizeof(SecChar) */ 428 size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar); 429 /* Add one character to clear tool warning */ 430 size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */ 431 432 /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */ 433 if (nextSize <= (size_t)SECUREC_MAX_WIDTH_LEN) { 434 void *nextBuffer = (void *)SECUREC_MALLOC(nextSize); 435 if (nextBuffer == NULL) { 436 return -1; 437 } 438 if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) { 439 SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ 440 return -1; 441 } 442 /* Clear old buffer memory */ 443 if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) { 444 SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ 445 return -1; 446 } 447 /* Free old allocated buffer */ 448 if (floatSpec->allocatedFloatStr != NULL) { 449 SECUREC_FREE(floatSpec->allocatedFloatStr); 450 } 451 floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer); /* Use to clear free on stack warning */ 452 floatSpec->floatStr = (SecChar *)(nextBuffer); 453 floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */ 454 return 0; 455 } 456 return -1; /* Next size is beyond max */ 457 } 458 return 0; 459} 460 461/* Do not use localeconv()->decimal_pointif only support '.' */ 462SECUREC_INLINE int SecIsFloatDecimal(SecChar ch) 463{ 464 return (int)(ch == SECUREC_CHAR('.')); 465} 466 467SECUREC_INLINE int SecInputFloatSign(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 468{ 469 if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) { 470 return 0; 471 } 472 spec->ch = SecGetChar(stream, &(spec->charCount)); 473 if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { 474 SECUREC_FILED_WIDTH_DEC(spec); /* Make sure the count after un get char is correct */ 475 if (spec->ch == SECUREC_CHAR('-')) { 476 floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('-'); 477 ++floatSpec->floatStrUsedLen; 478 if (SecExtendFloatLen(floatSpec) != 0) { 479 return -1; 480 } 481 } 482 } else { 483 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 484 } 485 return 0; 486} 487 488SECUREC_INLINE int SecInputFloatDigit(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 489{ 490 /* Now get integral part */ 491 while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 492 spec->ch = SecGetChar(stream, &(spec->charCount)); 493 if (SecIsDigit(spec->ch) == 0) { 494 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 495 return 0; 496 } 497 SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 498 spec->numberState = SECUREC_NUMBER_STATE_STARTED; 499 floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch; 500 ++floatSpec->floatStrUsedLen; 501 if (SecExtendFloatLen(floatSpec) != 0) { 502 return -1; 503 } 504 } 505 return 0; 506} 507 508/* 509* Scan value of exponent. 510* Return 0 OK 511*/ 512SECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 513{ 514 if (SecInputFloatSign(stream, spec, floatSpec) == -1) { 515 return -1; 516 } 517 if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 518 return -1; 519 } 520 return 0; 521} 522 523SECUREC_INLINE int SecInputFloatFractional(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 524{ 525 if (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 526 spec->ch = SecGetChar(stream, &(spec->charCount)); 527 if (SecIsFloatDecimal((SecChar)spec->ch) == 0) { 528 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 529 return 0; 530 } 531 SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 532 /* Now check for decimal */ 533 floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch; 534 ++floatSpec->floatStrUsedLen; 535 if (SecExtendFloatLen(floatSpec) != 0) { 536 return -1; 537 } 538 if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 539 return -1; 540 } 541 } 542 return 0; 543} 544 545SECUREC_INLINE int SecInputFloatExponent(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 546{ 547 /* Now get exponent part */ 548 if (spec->numberState == SECUREC_NUMBER_STATE_STARTED && SECUREC_FILED_WIDTH_ENOUGH(spec)) { 549 spec->ch = SecGetChar(stream, &(spec->charCount)); 550 if (spec->ch != SECUREC_CHAR('e') && spec->ch != SECUREC_CHAR('E')) { 551 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 552 return 0; 553 } 554 SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 555 floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('e'); 556 ++floatSpec->floatStrUsedLen; 557 if (SecExtendFloatLen(floatSpec) != 0) { 558 return -1; 559 } 560 if (SecInputFloatE(stream, spec, floatSpec) != 0) { 561 return -1; 562 } 563 } 564 return 0; 565} 566 567/* 568* Scan %f. 569* Return 0 OK 570*/ 571SECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) 572{ 573 floatSpec->floatStrUsedLen = 0; 574 575 /* The following code sequence is strict */ 576 if (SecInputFloatSign(stream, spec, floatSpec) != 0) { 577 return -1; 578 } 579 if (SecInputFloatDigit(stream, spec, floatSpec) != 0) { 580 return -1; 581 } 582 if (SecInputFloatFractional(stream, spec, floatSpec) != 0) { 583 return -1; 584 } 585 if (SecInputFloatExponent(stream, spec, floatSpec) != 0) { 586 return -1; 587 } 588 589 /* Make sure have a string terminator, buffer is large enough */ 590 floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0'); 591 if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) { 592 return 0; 593 } 594 return -1; 595} 596#endif 597 598#if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \ 599 (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)) 600/* only multi-bytes string need isleadbyte() function */ 601SECUREC_INLINE int SecIsLeadByte(SecInt ch) 602{ 603 unsigned int c = (unsigned int)ch; 604#if !(defined(_MSC_VER) || defined(_INC_WCTYPE)) 605 return (int)(c & 0x80U); /* Use bitwise operation to check if the most significant bit is 1 */ 606#else 607 return (int)isleadbyte((int)(c & 0xffU)); /* Use bitwise operations to limit character values to valid ranges */ 608#endif 609} 610#endif 611 612/* 613 * Parsing whether it is a wide character 614 */ 615SECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec) 616{ 617 if (spec->isWCharOrLong != 0) { 618 /* Wide character identifiers have been explicitly set by l or h flag */ 619 return; 620 } 621 622 /* Set default flag */ 623#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) 624 spec->isWCharOrLong = 1; /* On windows wide char version %c %s %[ is wide char */ 625#else 626 spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */ 627#endif 628 629 if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) { 630#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) 631 spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */ 632#else 633 spec->isWCharOrLong = 1; /* On linux all version %C %S is wide char */ 634#endif 635 } 636 637 return; 638} 639/* 640 * Decode %l %ll 641 */ 642SECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec) 643{ 644 const SecUnsignedChar *fmt = *format; 645 if (*(fmt + 1) == SECUREC_CHAR('l')) { 646 spec->numberArgType = 1; 647 spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 648 ++fmt; 649 } else { 650 spec->numberWidth = SECUREC_NUM_WIDTH_LONG; 651#if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 652 /* On window 64 system sizeof long is 32bit */ 653 spec->numberArgType = 1; 654#endif 655 spec->isWCharOrLong = 1; 656 } 657 *format = fmt; 658} 659 660/* 661 * Decode %I %I43 %I64 %Id %Ii %Io ... 662 * Set finishFlag to 1 finish Flag 663 */ 664SECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) 665{ 666 const SecUnsignedChar *fmt = *format; 667 if ((*(fmt + 1) == SECUREC_CHAR('6')) && 668 (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */ 669 spec->numberArgType = 1; 670 *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */ 671 } else if ((*(fmt + 1) == SECUREC_CHAR('3')) && 672 (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */ 673 *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */ 674 } else if ((*(fmt + 1) == SECUREC_CHAR('d')) || 675 (*(fmt + 1) == SECUREC_CHAR('i')) || 676 (*(fmt + 1) == SECUREC_CHAR('o')) || 677 (*(fmt + 1) == SECUREC_CHAR('x')) || 678 (*(fmt + 1) == SECUREC_CHAR('X'))) { 679 spec->numberArgType = SecNumberArgType(sizeof(void *)); 680 } else { 681 /* For %I */ 682 spec->numberArgType = SecNumberArgType(sizeof(void *)); 683 *finishFlag = 1; 684 } 685} 686 687SECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec) 688{ 689 const SecUnsignedChar *fmt = *format; 690 while (SecIsDigit((SecInt)(int)(*fmt)) != 0) { 691 spec->widthSet = 1; 692 if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) { 693 return -1; 694 } 695 spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0')); 696 ++fmt; 697 } 698 *format = fmt; 699 return 0; 700} 701 702/* 703 * Init default flags for each format. do not init ch this variable is context-dependent 704 */ 705SECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec) 706{ 707 /* The ch and charCount member variables cannot be initialized here */ 708 spec->argPtr = NULL; 709 spec->arrayWidth = 0; 710 spec->number64 = 0; 711 spec->number = 0; 712 spec->numberWidth = SECUREC_NUM_WIDTH_INT; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ 713 spec->numberArgType = 0; /* 1 for 64-bit integer, 0 otherwise */ 714 spec->width = 0; 715 spec->widthSet = 0; 716 spec->convChr = 0; 717 spec->oriConvChr = 0; 718 spec->isWCharOrLong = 0; 719 spec->suppress = 0; 720#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 721 spec->beyondMax = 0; 722#endif 723 spec->negative = 0; 724 spec->numberState = SECUREC_NUMBER_STATE_DEFAULT; 725} 726 727/* 728 * Decode qualifier %I %L %h ... 729 * Set finishFlag to 1 finish Flag 730 */ 731SECUREC_INLINE void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) 732{ 733 switch (**format) { 734 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 735 case SECUREC_CHAR('N'): 736 break; 737 case SECUREC_CHAR('h'): 738 --spec->numberWidth; /* The h for SHORT , hh for CHAR */ 739 spec->isWCharOrLong = -1; 740 break; 741#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 742 case SECUREC_CHAR('j'): 743 spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* For intmax_t or uintmax_t */ 744 spec->numberArgType = 1; 745 break; 746 case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */ 747#endif 748#if SECUREC_IN_KERNEL 749 case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */ 750#endif 751 case SECUREC_CHAR('z'): 752#ifdef SECUREC_ON_64BITS 753 spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 754 spec->numberArgType = 1; 755#else 756 spec->numberWidth = SECUREC_NUM_WIDTH_LONG; 757#endif 758 break; 759 case SECUREC_CHAR('L'): /* For long double */ /* fall-through */ /* FALLTHRU */ 760 case SECUREC_CHAR('q'): 761 spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; 762 spec->numberArgType = 1; 763 break; 764 case SECUREC_CHAR('l'): 765 SecDecodeScanQualifierL(format, spec); 766 break; 767 case SECUREC_CHAR('w'): 768 spec->isWCharOrLong = 1; 769 break; 770 case SECUREC_CHAR('*'): 771 spec->suppress = 1; 772 break; 773 case SECUREC_CHAR('I'): 774 SecDecodeScanQualifierI(format, spec, finishFlag); 775 break; 776 default: 777 *finishFlag = 1; 778 break; 779 } 780} 781/* 782 * Decode width and qualifier in format 783 */ 784SECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec) 785{ 786 const SecUnsignedChar *fmt = *format; 787 int finishFlag = 0; 788 789 do { 790 ++fmt; /* First skip % , next seek fmt */ 791 /* May %*6d , so put it inside the loop */ 792 if (SecDecodeScanWidth(&fmt, spec) != 0) { 793 return -1; 794 } 795 SecDecodeScanQualifier(&fmt, spec, &finishFlag); 796 } while (finishFlag == 0); 797 *format = fmt; 798 return 0; 799} 800 801/* 802 * Judging whether a zeroing buffer is needed according to different formats 803 */ 804SECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr) 805{ 806 const SecUnsignedChar *fmt = format; 807 /* To lowercase */ 808 int ch = SECUREC_TO_LOWERCASE(*fmt); 809 if (!(ch == 'c' || ch == 's' || ch == SECUREC_BRACE)) { 810 return -1; /* First argument is not a string type */ 811 } 812 if (ch == SECUREC_BRACE) { 813#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 814 if (*fmt == SECUREC_CHAR('{')) { 815 return -1; 816 } 817#endif 818 ++fmt; 819 if (*fmt == SECUREC_CHAR('^')) { 820 ++fmt; 821 } 822 if (*fmt == SECUREC_CHAR(']')) { 823 ++fmt; 824 } 825 while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { 826 ++fmt; 827 } 828 if (*fmt == SECUREC_CHAR('\0')) { 829 return -1; /* Trunc'd format string */ 830 } 831 } 832 *convChr = ch; 833 return 0; 834} 835 836/* 837 * Add L'\0' for wchar string , add '\0' for char string 838 */ 839SECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec) 840{ 841 if (spec->suppress == 0) { 842 *(char *)ptr = '\0'; 843#if SECUREC_HAVE_WCHART 844 if (spec->isWCharOrLong > 0) { 845 *(wchar_t UNALIGNED *)ptr = L'\0'; 846 } 847#endif 848 } 849} 850 851SECUREC_INLINE void SecDecodeClearArg(SecScanSpec *spec, va_list argList) 852{ 853 va_list argListSave; /* Backup for argList value, this variable don't need initialized */ 854 (void)SECUREC_MEMSET_FUNC_OPT(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */ 855#if defined(va_copy) 856 va_copy(argListSave, argList); 857#elif defined(__va_copy) /* For vxworks */ 858 __va_copy(argListSave, argList); 859#else 860 argListSave = argList; 861#endif 862 spec->argPtr = (void *)va_arg(argListSave, void *); 863 /* Get the next argument, size of the array in characters */ 864 /* Use 0xffffffffUL mask to Support pass integer as array length */ 865 spec->arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xffffffffUL; 866 va_end(argListSave); 867 /* To clear e438 last value assigned not used , the compiler will optimize this code */ 868 (void)argListSave; 869} 870 871#ifdef SECUREC_FOR_WCHAR 872/* 873 * Clean up the first %s %c buffer to zero for wchar version 874 */ 875void SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList) 876#else 877/* 878 * Clean up the first %s %c buffer to zero for char version 879 */ 880void SecClearDestBuf(const char *buffer, const char *format, va_list argList) 881#endif 882{ 883 SecScanSpec spec; 884 int convChr = 0; 885 const SecUnsignedChar *fmt = (const SecUnsignedChar *)format; 886 887 /* Find first % */ 888 while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) { 889 ++fmt; 890 } 891 if (*fmt == SECUREC_CHAR('\0')) { 892 return; 893 } 894 895 SecSetDefaultScanSpec(&spec); 896 if (SecDecodeScanFlag(&fmt, &spec) != 0) { 897 return; 898 } 899 900 /* Update wchar flag for %S %C */ 901 SecUpdateWcharFlagByType(*fmt, &spec); 902 if (spec.suppress != 0) { 903 return; 904 } 905 906 if (SecDecodeClearFormat(fmt, &convChr) != 0) { 907 return; 908 } 909 910 if (*buffer != SECUREC_CHAR('\0') && convChr != 's') { 911 /* 912 * When buffer not empty just clear %s. 913 * Example call sscanf by argment of (" \n", "%s", s, sizeof(s)) 914 */ 915 return; 916 } 917 918 SecDecodeClearArg(&spec, argList); 919 /* There is no need to judge the upper limit */ 920 if (spec.arrayWidth == 0 || spec.argPtr == NULL) { 921 return; 922 } 923 /* Clear one char */ 924 SecAddEndingZero(spec.argPtr, &spec); 925 return; 926} 927 928/* 929 * Assign number to output buffer 930 */ 931SECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec) 932{ 933 void *argPtr = spec->argPtr; 934 if (spec->numberArgType != 0) { 935#if defined(SECUREC_VXWORKS_PLATFORM) 936#if defined(SECUREC_VXWORKS_PLATFORM_COMP) 937 *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); 938#else 939 /* Take number64 as unsigned number unsigned to int clear Compile warning */ 940 *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64)); 941#endif 942#else 943 /* Take number64 as unsigned number */ 944 *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); 945#endif 946 return; 947 } 948 if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) { 949 /* Take number as unsigned number */ 950 *(long UNALIGNED *)argPtr = (long)(spec->number); 951 } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 952 *(int UNALIGNED *)argPtr = (int)(spec->number); 953 } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) { 954 /* Take number as unsigned number */ 955 *(short UNALIGNED *)argPtr = (short)(spec->number); 956 } else { /* < 0 for hh format modifier */ 957 /* Take number as unsigned number */ 958 *(char UNALIGNED *)argPtr = (char)(spec->number); 959 } 960} 961 962#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 963/* 964 * Judge the long bit width 965 */ 966SECUREC_INLINE int SecIsLongBitEqual(int bitNum) 967{ 968 return (int)((unsigned int)bitNum == SECUREC_LONG_BIT_NUM); 969} 970#endif 971 972/* 973 * Convert hexadecimal characters to decimal value 974 */ 975SECUREC_INLINE int SecHexValueOfChar(SecInt ch) 976{ 977 /* Use isdigit Causing tool false alarms */ 978 return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') : 979 ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */ 980} 981 982/* 983 * Parse decimal character to integer for 32bit . 984 */ 985static void SecDecodeNumberDecimal(SecScanSpec *spec) 986{ 987#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 988 unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN; 989#ifdef SECUREC_ON_64BITS 990 if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 991 decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN; 992 } 993#endif 994 if (spec->number > decimalEdge) { 995 spec->beyondMax = 1; 996 } 997#endif 998 spec->number = SECUREC_MUL_TEN(spec->number); 999#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1000 if (spec->number == SECUREC_MUL_TEN(decimalEdge)) { 1001 /* This code is specially converted to unsigned long type for compatibility */ 1002 SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number; 1003 if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) { 1004 spec->beyondMax = 1; 1005 } 1006 } 1007#endif 1008 spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 1009} 1010 1011/* 1012 * Parse Hex character to integer for 32bit . 1013 */ 1014static void SecDecodeNumberHex(SecScanSpec *spec) 1015{ 1016#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1017 if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) { 1018 spec->beyondMax = 1; 1019 } 1020#endif 1021 spec->number = SECUREC_MUL_SIXTEEN(spec->number); 1022 spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch); 1023} 1024 1025/* 1026 * Parse Octal character to integer for 32bit . 1027 */ 1028static void SecDecodeNumberOctal(SecScanSpec *spec) 1029{ 1030#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1031 if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) { 1032 spec->beyondMax = 1; 1033 } 1034#endif 1035 spec->number = SECUREC_MUL_EIGHT(spec->number); 1036 spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 1037} 1038 1039#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1040/* Compatible with integer negative values other than int */ 1041SECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec) 1042{ 1043 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1044 if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) { 1045 spec->number = SECUREC_MIN_LONG_NEG_VALUE; 1046 } else { 1047 spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 1048 } 1049 if (spec->beyondMax != 0) { 1050 if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) { 1051 spec->number = 0; 1052 } 1053 if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { 1054 spec->number = SECUREC_MIN_LONG_NEG_VALUE; 1055 } 1056 } 1057 } else { /* For o, u, x, X, p */ 1058 spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 1059 if (spec->beyondMax != 0) { 1060 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1061 } 1062 } 1063} 1064/* Compatible processing of integer negative numbers */ 1065SECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec) 1066{ 1067 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1068#ifdef SECUREC_ON_64BITS 1069 if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 1070 if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) { 1071 spec->number = 0; 1072 } else { 1073 spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 1074 } 1075 } 1076#else 1077 if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 1078 if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) { 1079 spec->number = SECUREC_MIN_32BITS_NEG_VALUE; 1080 } else { 1081 spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 1082 } 1083 } 1084#endif 1085 if (spec->beyondMax != 0) { 1086#ifdef SECUREC_ON_64BITS 1087 if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 1088 spec->number = 0; 1089 } 1090#else 1091 if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 1092 spec->number = SECUREC_MIN_32BITS_NEG_VALUE; 1093 } 1094#endif 1095 } 1096 } else { /* For o, u, x, X ,p */ 1097#ifdef SECUREC_ON_64BITS 1098 if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) { 1099 spec->number = SECUREC_MAX_32BITS_VALUE; 1100 } else { 1101 spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 1102 } 1103#else 1104 spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */ 1105#endif 1106 if (spec->beyondMax != 0) { 1107 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1108 } 1109 } 1110} 1111 1112/* Compatible with integer positive values other than int */ 1113SECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec) 1114{ 1115 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1116 if (spec->number > SECUREC_MAX_LONG_POS_VALUE) { 1117 spec->number = SECUREC_MAX_LONG_POS_VALUE; 1118 } 1119 if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) { 1120 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1121 } 1122 if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { 1123 spec->number = SECUREC_MAX_LONG_POS_VALUE; 1124 } 1125 } else { 1126 if (spec->beyondMax != 0) { 1127 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1128 } 1129 } 1130} 1131 1132/* Compatible processing of integer positive numbers */ 1133SECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec) 1134{ 1135 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1136#ifdef SECUREC_ON_64BITS 1137 if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 1138 if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) { 1139 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1140 } 1141 } 1142 if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) { 1143 spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE; 1144 } 1145#else 1146 if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 1147 if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) { 1148 spec->number = SECUREC_MAX_32BITS_POS_VALUE; 1149 } 1150 } 1151 if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) { 1152 spec->number = SECUREC_MAX_32BITS_POS_VALUE; 1153 } 1154#endif 1155 } else { /* For o,u,x,X,p */ 1156 if (spec->beyondMax != 0) { 1157 spec->number = SECUREC_MAX_32BITS_VALUE; 1158 } 1159 } 1160} 1161 1162#endif 1163 1164/* 1165 * Parse decimal character to integer for 64bit . 1166 */ 1167static void SecDecodeNumber64Decimal(SecScanSpec *spec) 1168{ 1169#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1170 if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) { 1171 spec->beyondMax = 1; 1172 } 1173#endif 1174 spec->number64 = SECUREC_MUL_TEN(spec->number64); 1175#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1176 if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) { 1177 SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64; 1178 if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) { 1179 spec->beyondMax = 1; 1180 } 1181 } 1182#endif 1183 spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 1184} 1185 1186/* 1187 * Parse Hex character to integer for 64bit . 1188 */ 1189static void SecDecodeNumber64Hex(SecScanSpec *spec) 1190{ 1191#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1192 if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) { 1193 spec->beyondMax = 1; 1194 } 1195#endif 1196 spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64); 1197 spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch); 1198} 1199 1200/* 1201 * Parse Octal character to integer for 64bit . 1202 */ 1203static void SecDecodeNumber64Octal(SecScanSpec *spec) 1204{ 1205#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1206 if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) { 1207 spec->beyondMax = 1; 1208 } 1209#endif 1210 spec->number64 = SECUREC_MUL_EIGHT(spec->number64); 1211 spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')); 1212} 1213 1214#define SECUREC_DECODE_NUMBER_FUNC_NUM 2 1215 1216/* 1217 * Parse 64-bit integer formatted input, return 0 when ch is a number. 1218 */ 1219SECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec) 1220{ 1221 /* Function name cannot add address symbol, causing 546 alarm */ 1222 static void (* const secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 1223 SecDecodeNumberHex, SecDecodeNumber64Hex 1224 }; 1225 static void (* const secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 1226 SecDecodeNumberOctal, SecDecodeNumber64Octal 1227 }; 1228 static void (* const secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 1229 SecDecodeNumberDecimal, SecDecodeNumber64Decimal 1230 }; 1231 if (spec->convChr == 'x' || spec->convChr == 'p') { 1232 if (SecIsXdigit(spec->ch) != 0) { 1233 (*secDecodeNumberHex[spec->numberArgType])(spec); 1234 } else { 1235 return -1; 1236 } 1237 return 0; 1238 } 1239 if (SecIsDigit(spec->ch) == 0) { 1240 return -1; 1241 } 1242 if (spec->convChr == 'o') { 1243 if (spec->ch < SECUREC_CHAR('8')) { /* Octal maximum limit '8' */ 1244 (*secDecodeNumberOctal[spec->numberArgType])(spec); 1245 } else { 1246 return -1; 1247 } 1248 } else { /* The convChr is 'd' */ 1249 (*secDecodeNumberDecimal[spec->numberArgType])(spec); 1250 } 1251 return 0; 1252} 1253 1254/* 1255 * Complete the final 32-bit integer formatted input 1256 */ 1257static void SecFinishNumber(SecScanSpec *spec) 1258{ 1259#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1260 if (spec->negative != 0) { 1261 if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 1262 SecFinishNumberNegativeInt(spec); 1263 } else { 1264 SecFinishNumberNegativeOther(spec); 1265 } 1266 } else { 1267 if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { 1268 SecFinishNumberPositiveInt(spec); 1269 } else { 1270 SecFinishNumberPositiveOther(spec); 1271 } 1272 } 1273#else 1274 if (spec->negative != 0) { 1275#if defined(__hpux) 1276 if (spec->oriConvChr != 'p') { 1277 spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 1278 } 1279#else 1280 spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */ 1281#endif 1282 } 1283#endif 1284 return; 1285} 1286 1287/* 1288 * Complete the final 64-bit integer formatted input 1289 */ 1290static void SecFinishNumber64(SecScanSpec *spec) 1291{ 1292#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) 1293 if (spec->negative != 0) { 1294 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1295 if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) { 1296 spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; 1297 } else { 1298 spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 1299 } 1300 if (spec->beyondMax != 0) { 1301 spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; 1302 } 1303 } else { /* For o, u, x, X, p */ 1304 spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 1305 if (spec->beyondMax != 0) { 1306 spec->number64 = SECUREC_MAX_64BITS_VALUE; 1307 } 1308 } 1309 } else { 1310 if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) { 1311 if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) { 1312 spec->number64 = SECUREC_MAX_64BITS_POS_VALUE; 1313 } 1314 if (spec->beyondMax != 0) { 1315 spec->number64 = SECUREC_MAX_64BITS_POS_VALUE; 1316 } 1317 } else { 1318 if (spec->beyondMax != 0) { 1319 spec->number64 = SECUREC_MAX_64BITS_VALUE; 1320 } 1321 } 1322 } 1323#else 1324 if (spec->negative != 0) { 1325#if defined(__hpux) 1326 if (spec->oriConvChr != 'p') { 1327 spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 1328 } 1329#else 1330 spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */ 1331#endif 1332 } 1333#endif 1334 return; 1335} 1336 1337#if SECUREC_ENABLE_SCANF_FILE 1338 1339/* 1340 * Adjust the pointer position of the file stream 1341 */ 1342SECUREC_INLINE void SecSeekStream(SecFileStream *stream) 1343{ 1344 if (stream->count == 0) { 1345 if (feof(stream->pf) != 0) { 1346 /* File pointer at the end of file, don't need to seek back */ 1347 stream->base[0] = '\0'; 1348 return; 1349 } 1350 } 1351 /* Seek to original position, for file read, but nothing to input */ 1352 if (fseek(stream->pf, stream->oriFilePos, SEEK_SET) != 0) { 1353 /* Seek failed, ignore it */ 1354 stream->oriFilePos = 0; 1355 return; 1356 } 1357 1358 if (stream->fileRealRead > 0) { /* Do not seek without input data */ 1359#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1360 size_t residue = stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE; 1361 size_t loops; 1362 for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) { 1363 if (fread(stream->base, (size_t)SECUREC_BUFFERED_BLOK_SIZE, (size_t)1, stream->pf) != (size_t)1) { 1364 break; 1365 } 1366 } 1367 if (residue != 0) { 1368 long curFilePos; 1369 if (fread(stream->base, residue, (size_t)1, stream->pf) != (size_t)1) { 1370 return; 1371 } 1372 curFilePos = ftell(stream->pf); 1373 if (curFilePos < stream->oriFilePos || 1374 (size_t)(unsigned long)(curFilePos - stream->oriFilePos) < stream->fileRealRead) { 1375 /* Try to remedy the problem */ 1376 long adjustNum = (long)(stream->fileRealRead - (size_t)(unsigned long)(curFilePos - stream->oriFilePos)); 1377 (void)fseek(stream->pf, adjustNum, SEEK_CUR); 1378 } 1379 } 1380#else 1381 /* Seek from oriFilePos. Regardless of the integer sign problem, call scanf will not read very large data */ 1382 if (fseek(stream->pf, (long)stream->fileRealRead, SEEK_CUR) != 0) { 1383 /* Seek failed, ignore it */ 1384 stream->oriFilePos = 0; 1385 return; 1386 } 1387#endif 1388 } 1389 return; 1390} 1391 1392/* 1393 * Adjust the pointer position of the file stream and free memory 1394 */ 1395SECUREC_INLINE void SecAdjustStream(SecFileStream *stream) 1396{ 1397 if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0 && stream->base != NULL) { 1398 SecSeekStream(stream); 1399 SECUREC_FREE(stream->base); 1400 stream->base = NULL; 1401 } 1402 return; 1403} 1404#endif 1405 1406SECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format) 1407{ 1408 const SecUnsignedChar *fmt = *format; 1409 while (SecIsSpace((SecInt)(int)(*fmt)) != 0) { 1410 ++fmt; 1411 } 1412 *format = fmt; 1413} 1414 1415#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) 1416/* 1417 * Handling multi-character characters 1418 */ 1419SECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream) 1420{ 1421#if SECUREC_HAVE_MBTOWC 1422 const SecUnsignedChar *fmt = *format; 1423 int ch1 = (int)spec->ch; 1424 int ch2 = SecGetChar(stream, &(spec->charCount)); 1425 spec->ch = (SecInt)ch2; 1426 if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) { 1427 /* in console mode, ungetc twice may cause problem */ 1428 SecUnGetChar(ch2, stream, &(spec->charCount)); 1429 SecUnGetChar(ch1, stream, &(spec->charCount)); 1430 return -1; 1431 } 1432 ++fmt; 1433 if ((unsigned int)MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE && 1434 (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) && 1435 (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) { 1436 /* This char is very likely to be a UTF-8 char */ 1437 wchar_t tempWChar; 1438 char temp[SECUREC_MULTI_BYTE_MAX_LEN]; 1439 int ch3 = (int)SecGetChar(stream, &(spec->charCount)); 1440 spec->ch = (SecInt)ch3; 1441 if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) { 1442 SecUnGetChar(ch3, stream, &(spec->charCount)); 1443 return -1; 1444 } 1445 temp[0] = (char)ch1; 1446 temp[1] = (char)ch2; /* 1 index of second character */ 1447 temp[2] = (char)ch3; /* 2 index of third character */ 1448 temp[3] = '\0'; /* 3 of string terminator position */ 1449 if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) { 1450 /* Succeed */ 1451 ++fmt; 1452 --spec->charCount; 1453 } else { 1454 SecUnGetChar(ch3, stream, &(spec->charCount)); 1455 } 1456 } 1457 --spec->charCount; /* Only count as one character read */ 1458 *format = fmt; 1459 return 0; 1460#else 1461 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 1462 (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 1463 return -1; 1464#endif 1465} 1466 1467SECUREC_INLINE int SecFilterWcharInFormat(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream) 1468{ 1469 if (SecIsLeadByte(spec->ch) != 0) { 1470 if (SecDecodeLeadByte(spec, format, stream) != 0) { 1471 return -1; 1472 } 1473 } 1474 return 0; 1475} 1476#endif 1477 1478/* 1479 * Resolving sequence of characters from %[ format, format wile point to ']' 1480 */ 1481SECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable) 1482{ 1483 const SecUnsignedChar *fmt = *format; 1484 SecUnsignedChar prevChar = 0; 1485#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) 1486 if (*fmt == SECUREC_CHAR('{')) { 1487 return -1; 1488 } 1489#endif 1490 /* For building "table" data */ 1491 ++fmt; /* Skip [ */ 1492 bracketTable->mask = 0; /* Set all bits to 0 */ 1493 if (*fmt == SECUREC_CHAR('^')) { 1494 ++fmt; 1495 bracketTable->mask = (unsigned char)0xffU; /* Use 0xffU to set all bits to 1 */ 1496 } 1497 if (*fmt == SECUREC_CHAR(']')) { 1498 prevChar = SECUREC_CHAR(']'); 1499 ++fmt; 1500 SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']')); 1501 } 1502 while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { 1503 SecUnsignedChar expCh = *fmt; 1504 ++fmt; 1505 if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) { 1506 /* Normal character */ 1507 prevChar = expCh; 1508 SecBracketSetBit(bracketTable->table, expCh); 1509 } else { 1510 /* For %[a-z] */ 1511 expCh = *fmt; /* Get end of range */ 1512 ++fmt; 1513 if (prevChar <= expCh) { /* %[a-z] %[a-a] */ 1514 SecBracketSetBitRange(bracketTable->table, prevChar, expCh); 1515 } else { 1516 /* For %[z-a] */ 1517#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1518 /* Swap start and end characters */ 1519 SecBracketSetBitRange(bracketTable->table, expCh, prevChar); 1520#else 1521 SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-')); 1522 SecBracketSetBit(bracketTable->table, expCh); 1523#endif 1524 } 1525 prevChar = 0; 1526 } 1527 } 1528 *format = fmt; 1529 return 0; 1530} 1531 1532#ifdef SECUREC_FOR_WCHAR 1533SECUREC_INLINE int SecInputForWchar(SecScanSpec *spec) 1534{ 1535 void *endPtr = spec->argPtr; 1536 if (spec->isWCharOrLong > 0) { 1537 *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch; 1538 endPtr = (wchar_t *)endPtr + 1; 1539 --spec->arrayWidth; 1540 } else { 1541#if SECUREC_HAVE_WCTOMB 1542 int temp; 1543 char tmpBuf[SECUREC_MB_LEN + 1]; 1544 SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch); 1545 SECUREC_END_MASK_MSVC_CRT_WARNING 1546 if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) { 1547 /* If wctomb error, then ignore character */ 1548 return 0; 1549 } 1550 if (((size_t)(unsigned int)temp) > spec->arrayWidth) { 1551 return -1; 1552 } 1553 if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) { 1554 return -1; 1555 } 1556 endPtr = (char *)endPtr + temp; 1557 spec->arrayWidth -= (size_t)(unsigned int)temp; 1558#else 1559 return -1; 1560#endif 1561 } 1562 spec->argPtr = endPtr; 1563 return 0; 1564} 1565#endif 1566 1567#ifndef SECUREC_FOR_WCHAR 1568#if SECUREC_HAVE_WCHART 1569SECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream) 1570{ 1571 wchar_t tempWChar = L'?'; /* Set default char is ? */ 1572#if SECUREC_HAVE_MBTOWC 1573 char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1]; 1574 temp[0] = (char)spec->ch; 1575 temp[1] = '\0'; 1576#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1577 if (SecIsLeadByte(spec->ch) != 0) { 1578 spec->ch = SecGetChar(stream, &(spec->charCount)); 1579 temp[1] = (char)spec->ch; 1580 temp[2] = '\0'; /* 2 of string terminator position */ 1581 } 1582 if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { 1583 /* No string termination error for tool */ 1584 tempWChar = L'?'; 1585 } 1586#else 1587 if (SecIsLeadByte(spec->ch) != 0) { 1588 int convRes = 0; 1589 int di = 1; 1590 /* On Linux like system, the string is encoded in UTF-8 */ 1591 while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) { 1592 spec->ch = SecGetChar(stream, &(spec->charCount)); 1593 temp[di] = (char)spec->ch; 1594 ++di; 1595 temp[di] = '\0'; 1596 convRes = mbtowc(&tempWChar, temp, sizeof(temp)); 1597 } 1598 if (convRes <= 0) { 1599 tempWChar = L'?'; 1600 } 1601 } else { 1602 if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { 1603 tempWChar = L'?'; 1604 } 1605 } 1606#endif 1607#else 1608 (void)spec; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 1609 (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 1610#endif /* SECUREC_HAVE_MBTOWC */ 1611 1612 return tempWChar; 1613} 1614#endif /* SECUREC_HAVE_WCHART */ 1615 1616SECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream) 1617{ 1618 void *endPtr = spec->argPtr; 1619 if (spec->isWCharOrLong > 0) { 1620#if SECUREC_HAVE_WCHART 1621 *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream); 1622 endPtr = (wchar_t *)endPtr + 1; 1623 --spec->arrayWidth; 1624#else 1625 (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 1626 return -1; 1627#endif 1628 } else { 1629 *(char *)endPtr = (char)spec->ch; 1630 endPtr = (char *)endPtr + 1; 1631 --spec->arrayWidth; 1632 } 1633 spec->argPtr = endPtr; 1634 return 0; 1635} 1636#endif 1637 1638/* 1639 * Scan digital part of %d %i %o %u %x %p. 1640 * Return 0 OK 1641 */ 1642SECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec) 1643{ 1644 static void (* const secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = { 1645 SecFinishNumber, SecFinishNumber64 1646 }; 1647 while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 1648 spec->ch = SecGetChar(stream, &(spec->charCount)); 1649 /* Decode ch to number */ 1650 if (SecDecodeNumber(spec) != 0) { 1651 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 1652 break; 1653 } 1654 SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */ 1655 spec->numberState = SECUREC_NUMBER_STATE_STARTED; 1656 } 1657 /* Handling integer negative numbers and beyond max */ 1658 (*secFinishNumber[spec->numberArgType])(spec); 1659 if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) { 1660 return 0; 1661 } 1662 return -1; 1663} 1664 1665/* 1666 * Scan %d %i %o %u %x %p. 1667 * Return 0 OK 1668 */ 1669SECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec) 1670{ 1671 /* Character already read */ 1672 if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { 1673 if (spec->ch == SECUREC_CHAR('-')) { 1674 spec->negative = 1; 1675#if SECUREC_IN_KERNEL 1676 /* In kernel Refuse to enter negative number */ 1677 if (SECUREC_CONVERT_IS_UNSIGNED(spec->oriConvChr)) { 1678 return -1; 1679 } 1680#endif 1681 } 1682 SECUREC_FILED_WIDTH_DEC(spec); /* Do not need to check width here, must be greater than 0 */ 1683 spec->ch = SecGetChar(stream, &(spec->charCount)); /* Eat + or - */ 1684 spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next character, used for the '0' judgments */ 1685 SecUnGetChar(spec->ch, stream, &(spec->charCount)); /* Not sure if it was actually read, so push back */ 1686 } 1687 1688 if (spec->oriConvChr == 'i') { 1689 spec->convChr = 'd'; /* The i could be d, o, or x, use d as default */ 1690 } 1691 1692 if (spec->ch == SECUREC_CHAR('0') && (spec->oriConvChr == 'x' || spec->oriConvChr == 'i') && 1693 SECUREC_FILED_WIDTH_ENOUGH(spec)) { 1694 /* Input string begin with 0, may be 0x123 0X123 0123 0x 01 0yy 09 0 0ab 00 */ 1695 SECUREC_FILED_WIDTH_DEC(spec); 1696 spec->ch = SecGetChar(stream, &(spec->charCount)); /* ch is '0' */ 1697 1698 /* Read only '0' due to width limitation */ 1699 if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) { 1700 /* The number or number64 in spec has been set 0 */ 1701 return 0; 1702 } 1703 1704 spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next char to check x or X, do not dec width */ 1705 if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) { 1706 spec->convChr = 'x'; 1707 SECUREC_FILED_WIDTH_DEC(spec); /* Make incorrect width for x or X */ 1708 } else { 1709 if (spec->oriConvChr == 'i') { 1710 spec->convChr = 'o'; 1711 } 1712 /* For "0y" "08" "01" "0a" ... ,push the 'y' '8' '1' 'a' back */ 1713 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 1714 /* Since 0 has been read, it indicates that a valid character has been read */ 1715 spec->numberState = SECUREC_NUMBER_STATE_STARTED; 1716 } 1717 } 1718 return SecInputNumberDigital(stream, spec); 1719} 1720 1721/* 1722 * Scan %c %s %[ 1723 * Return 0 OK 1724 */ 1725SECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec, 1726 const SecBracketTable *bracketTable, int *doneCount) 1727{ 1728 void *startPtr = spec->argPtr; 1729 int suppressed = 0; 1730 int errNoMem = 0; 1731 1732 while (SECUREC_FILED_WIDTH_ENOUGH(spec)) { 1733 SECUREC_FILED_WIDTH_DEC(spec); 1734 spec->ch = SecGetChar(stream, &(spec->charCount)); 1735 /* 1736 * The char condition or string condition and bracket condition. 1737 * Only supports wide characters with a maximum length of two bytes 1738 */ 1739 if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) != 0 || 1740 SecCanInputString(spec->convChr, spec->ch) != 0 || 1741 SecCanInputForBracket(spec->convChr, spec->ch, bracketTable) != 0)) { 1742 if (spec->suppress != 0) { 1743 /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */ 1744 suppressed = 1; 1745 continue; 1746 } 1747 /* Now suppress is not set */ 1748 if (spec->arrayWidth == 0) { 1749 errNoMem = 1; /* We have exhausted the user's buffer */ 1750 break; 1751 } 1752#ifdef SECUREC_FOR_WCHAR 1753 errNoMem = SecInputForWchar(spec); 1754#else 1755 errNoMem = SecInputForChar(spec, stream); 1756#endif 1757 if (errNoMem != 0) { 1758 break; 1759 } 1760 } else { 1761 SecUnGetChar(spec->ch, stream, &(spec->charCount)); 1762 break; 1763 } 1764 } 1765 1766 if (errNoMem != 0) { 1767 /* In case of error, blank out the input buffer */ 1768 SecAddEndingZero(startPtr, spec); 1769 return -1; 1770 } 1771 if ((spec->suppress != 0 && suppressed == 0) || 1772 (spec->suppress == 0 && startPtr == spec->argPtr)) { 1773 /* No input was scanned */ 1774 return -1; 1775 } 1776 if (spec->convChr != 'c') { 1777 /* Add null-terminate for strings */ 1778 SecAddEndingZero(spec->argPtr, spec); 1779 } 1780 if (spec->suppress == 0) { 1781 *doneCount = *doneCount + 1; 1782 } 1783 return 0; 1784} 1785 1786#ifdef SECUREC_FOR_WCHAR 1787/* 1788 * Allocate buffer for wchar version of %[. 1789 * Return 0 OK 1790 */ 1791SECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable) 1792{ 1793 if (bracketTable->table == NULL) { 1794 /* Table should be freed after use */ 1795 bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE); 1796 if (bracketTable->table == NULL) { 1797 return -1; 1798 } 1799 } 1800 return 0; 1801} 1802 1803/* 1804 * Free buffer for wchar version of %[ 1805 */ 1806SECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable) 1807{ 1808 if (bracketTable->table != NULL) { 1809 SECUREC_FREE(bracketTable->table); 1810 bracketTable->table = NULL; 1811 } 1812} 1813#endif 1814 1815#ifdef SECUREC_FOR_WCHAR 1816/* 1817 * Formatting input core functions for wchar version.Called by a function such as vswscanf_s 1818 */ 1819int SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList) 1820#else 1821/* 1822 * Formatting input core functions for char version.Called by a function such as vsscanf_s 1823 */ 1824int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) 1825#endif 1826{ 1827 const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat; 1828 SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE; 1829 SecScanSpec spec; 1830 int doneCount = 0; 1831 int formatError = 0; 1832 int paraIsNull = 0; 1833 int match = 0; /* When % is found , inc this value */ 1834 int errRet = 0; 1835#if SECUREC_ENABLE_SCANF_FLOAT 1836 SecFloatSpec floatSpec; 1837 SecInitFloatSpec(&floatSpec); 1838#endif 1839 spec.ch = 0; /* Need to initialize to 0 */ 1840 spec.charCount = 0; /* Need to initialize to 0 */ 1841 1842 /* Format must not NULL, use err < 1 to clear 845 */ 1843 while (errRet < 1 && *format != SECUREC_CHAR('\0')) { 1844 /* Skip space in format and space in input */ 1845 if (SecIsSpace((SecInt)(int)(*format)) != 0) { 1846 /* Read first no space char */ 1847 spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); 1848 /* Read the EOF cannot be returned directly here, because the case of " %n" needs to be handled */ 1849 /* Put fist no space char backup. put EOF back is also OK, and to modify the character count */ 1850 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 1851 SecSkipSpaceFormat(&format); 1852 continue; 1853 } 1854 1855 if (*format != SECUREC_CHAR('%')) { 1856 spec.ch = SecGetChar(stream, &(spec.charCount)); 1857 if ((int)(*format) != (int)(spec.ch)) { 1858 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 1859 break; 1860 } 1861 ++format; 1862#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) 1863 if (SecFilterWcharInFormat(&spec, &format, stream) != 0) { 1864 break; 1865 } 1866#endif 1867 continue; 1868 } 1869 1870 /* Now *format is % */ 1871 /* Set default value for each % */ 1872 SecSetDefaultScanSpec(&spec); 1873 if (SecDecodeScanFlag(&format, &spec) != 0) { 1874 formatError = 1; 1875 ++errRet; 1876 continue; 1877 } 1878 if (!SECUREC_FILED_WIDTH_ENOUGH(&spec)) { 1879 /* 0 width in format */ 1880 ++errRet; 1881 continue; 1882 } 1883 1884 /* Update wchar flag for %S %C */ 1885 SecUpdateWcharFlagByType(*format, &spec); 1886 1887 spec.convChr = SECUREC_TO_LOWERCASE(*format); 1888 spec.oriConvChr = spec.convChr; /* convChr may be modified to handle integer logic */ 1889 if (spec.convChr != 'n') { 1890 if (spec.convChr != 'c' && spec.convChr != SECUREC_BRACE) { 1891 spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); 1892 } else { 1893 spec.ch = SecGetChar(stream, &(spec.charCount)); 1894 } 1895 if (spec.ch == SECUREC_EOF) { 1896 ++errRet; 1897 continue; 1898 } 1899 } 1900 1901 /* Now no 0 width in format and get one char from input */ 1902 switch (spec.oriConvChr) { 1903 case 'c': /* Also 'C' */ 1904 if (spec.widthSet == 0) { 1905 spec.widthSet = 1; 1906 spec.width = 1; 1907 } 1908 /* fall-through */ /* FALLTHRU */ 1909 case 's': /* Also 'S': */ 1910 /* fall-through */ /* FALLTHRU */ 1911 case SECUREC_BRACE: 1912 /* Unset last char to stream */ 1913 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 1914 /* Check dest buffer and size */ 1915 if (spec.suppress == 0) { 1916 spec.argPtr = (void *)va_arg(argList, void *); 1917 if (spec.argPtr == NULL) { 1918 paraIsNull = 1; 1919 ++errRet; 1920 continue; 1921 } 1922 /* Get the next argument, size of the array in characters */ 1923 spec.arrayWidth = SECUREC_GET_ARRAYWIDTH(argList); 1924 if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) { 1925 /* Do not clear buffer just go error */ 1926 ++errRet; 1927 continue; 1928 } 1929 /* One element is needed for '\0' for %s and %[ */ 1930 if (spec.convChr != 'c') { 1931 --spec.arrayWidth; 1932 } 1933 } else { 1934 /* Set argPtr to NULL is necessary, in suppress mode we don't use argPtr to store data */ 1935 spec.argPtr = NULL; 1936 } 1937 1938 if (spec.convChr == SECUREC_BRACE) { 1939 /* Malloc when first %[ is meet for wchar version */ 1940#ifdef SECUREC_FOR_WCHAR 1941 if (SecAllocBracketTable(&bracketTable) != 0) { 1942 ++errRet; 1943 continue; 1944 } 1945#endif 1946 (void)SECUREC_MEMSET_FUNC_OPT(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE); 1947 if (SecSetupBracketTable(&format, &bracketTable) != 0) { 1948 ++errRet; 1949 continue; 1950 } 1951 1952 if (*format == SECUREC_CHAR('\0')) { 1953 /* Default add string terminator */ 1954 SecAddEndingZero(spec.argPtr, &spec); 1955 ++errRet; 1956 /* Truncated format */ 1957 continue; 1958 } 1959 } 1960 1961 /* Set completed. Now read string or character */ 1962 if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) { 1963 ++errRet; 1964 continue; 1965 } 1966 break; 1967 case 'p': 1968 /* Make %hp same as %p */ 1969 spec.numberWidth = SECUREC_NUM_WIDTH_INT; 1970#ifdef SECUREC_ON_64BITS 1971 spec.numberArgType = 1; 1972#endif 1973 /* fall-through */ /* FALLTHRU */ 1974 case 'o': /* fall-through */ /* FALLTHRU */ 1975 case 'u': /* fall-through */ /* FALLTHRU */ 1976 case 'd': /* fall-through */ /* FALLTHRU */ 1977 case 'i': /* fall-through */ /* FALLTHRU */ 1978 case 'x': 1979 /* Unset last char to stream */ 1980 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 1981 if (SecInputNumber(stream, &spec) != 0) { 1982 ++errRet; 1983 continue; 1984 } 1985 if (spec.suppress == 0) { 1986 spec.argPtr = (void *)va_arg(argList, void *); 1987 if (spec.argPtr == NULL) { 1988 paraIsNull = 1; 1989 ++errRet; 1990 continue; 1991 } 1992 SecAssignNumber(&spec); 1993 ++doneCount; 1994 } 1995 break; 1996 case 'n': /* Char count */ 1997 if (spec.suppress == 0) { 1998 spec.argPtr = (void *)va_arg(argList, void *); 1999 if (spec.argPtr == NULL) { 2000 paraIsNull = 1; 2001 ++errRet; 2002 continue; 2003 } 2004 spec.number = (unsigned long)(unsigned int)(spec.charCount); 2005 spec.numberArgType = 0; 2006 SecAssignNumber(&spec); 2007 } 2008 break; 2009 case 'e': /* fall-through */ /* FALLTHRU */ 2010 case 'f': /* fall-through */ /* FALLTHRU */ 2011 case 'g': /* Scan a float */ 2012 /* Unset last char to stream */ 2013 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 2014#if SECUREC_ENABLE_SCANF_FLOAT 2015 if (SecInputFloat(stream, &spec, &floatSpec) != 0) { 2016 ++errRet; 2017 continue; 2018 } 2019 if (spec.suppress == 0) { 2020 spec.argPtr = (void *)va_arg(argList, void *); 2021 if (spec.argPtr == NULL) { 2022 ++errRet; 2023 paraIsNull = 1; 2024 continue; 2025 } 2026 if (SecAssignFloat(&floatSpec, &spec) != 0) { 2027 ++errRet; 2028 continue; 2029 } 2030 ++doneCount; 2031 } 2032 break; 2033#else /* SECUREC_ENABLE_SCANF_FLOAT */ 2034 ++errRet; 2035 continue; 2036#endif 2037 default: 2038 if ((int)(*format) != (int)spec.ch) { 2039 SecUnGetChar(spec.ch, stream, &(spec.charCount)); 2040 formatError = 1; 2041 ++errRet; 2042 continue; 2043 } else { 2044 --match; /* Compensate for the self-increment of the following code */ 2045 } 2046 break; 2047 } 2048 ++match; 2049 ++format; 2050 } 2051 2052#ifdef SECUREC_FOR_WCHAR 2053 SecFreeBracketTable(&bracketTable); 2054#endif 2055 2056#if SECUREC_ENABLE_SCANF_FLOAT 2057 SecFreeFloatSpec(&floatSpec, &doneCount); 2058#endif 2059 2060#if SECUREC_ENABLE_SCANF_FILE 2061 SecAdjustStream(stream); 2062#endif 2063 2064 if (spec.ch == SECUREC_EOF) { 2065 return ((doneCount != 0 || match != 0) ? doneCount : SECUREC_SCANF_EINVAL); 2066 } 2067 if (formatError != 0 || paraIsNull != 0) { 2068 /* Invalid Input Format or parameter, but not meet EOF */ 2069 return SECUREC_SCANF_ERROR_PARA; 2070 } 2071 return doneCount; 2072} 2073 2074#if SECUREC_ENABLE_SCANF_FILE 2075/* 2076 * Get char from stream use std function 2077 */ 2078SECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream) 2079{ 2080 SecInt ch; 2081 ch = SECUREC_GETC(stream->pf); 2082 return ch; 2083} 2084 2085/* 2086 * Try to read the BOM header, when meet a BOM head, discard it, then data is Aligned to base 2087 */ 2088SECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream) 2089{ 2090 /* Use size_t type conversion to clean e747 */ 2091 stream->count = fread(stream->base, (size_t)1, (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf); 2092 if (stream->count > SECUREC_BOM_HEADER_SIZE) { 2093 stream->count = 0; 2094 } 2095 if (SECUREC_BEGIN_WITH_BOM(stream->base, stream->count)) { 2096 /* It's BOM header, discard it */ 2097 stream->count = 0; 2098 } 2099} 2100 2101/* 2102 * Get char from file stream or buffer 2103 */ 2104SECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream) 2105{ 2106 SecInt ch; 2107 if (stream->count < sizeof(SecChar)) { 2108 /* Load file to buffer */ 2109 size_t len; 2110 if (stream->base != NULL) { 2111 /* Put the last unread data in the buffer head */ 2112 for (len = 0; len < stream->count; ++len) { 2113 stream->base[len] = stream->cur[len]; 2114 } 2115 } else { 2116 stream->oriFilePos = ftell(stream->pf); /* Save original file read position */ 2117 if (stream->oriFilePos == -1) { 2118 /* It may be a pipe stream */ 2119 stream->flag = SECUREC_PIPE_STREAM_FLAG; 2120 return SecGetCharFromStream(stream); 2121 } 2122 /* Reserve the length of BOM head */ 2123 stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + 2124 SECUREC_BOM_HEADER_SIZE + sizeof(SecChar)); /* To store '\0' and aligned to wide char */ 2125 if (stream->base == NULL) { 2126 return SECUREC_EOF; 2127 } 2128 /* First read file */ 2129 if (stream->oriFilePos == 0) { 2130 /* Make sure the data is aligned to base */ 2131 SecReadAndSkipBomHeader(stream); 2132 } 2133 } 2134 2135 /* Skip existing data and read data */ 2136 len = fread(stream->base + stream->count, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf); 2137 if (len > SECUREC_BUFFERED_BLOK_SIZE) { /* It won't happen, */ 2138 len = 0; 2139 } 2140 stream->count += len; 2141 stream->cur = stream->base; 2142 stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG; 2143 stream->base[stream->count] = '\0'; /* For tool Warning string null */ 2144 } 2145 2146 SECUREC_GET_CHAR(stream, &ch); 2147 if (ch != SECUREC_EOF) { 2148 stream->fileRealRead += sizeof(SecChar); 2149 } 2150 return ch; 2151} 2152#endif 2153 2154/* 2155 * Get char for wchar version 2156 */ 2157SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter) 2158{ 2159 *counter = *counter + 1; /* Always plus 1 */ 2160 /* The main scenario is scanf str */ 2161 if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) { 2162 SecInt ch; 2163 SECUREC_GET_CHAR(stream, &ch); 2164 return ch; 2165 } 2166#if SECUREC_ENABLE_SCANF_FILE 2167 if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0) { 2168 return SecGetCharFromFile(stream); 2169 } 2170 if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) { 2171 return SecGetCharFromStream(stream); 2172 } 2173#endif 2174 return SECUREC_EOF; 2175} 2176 2177/* 2178 * Unget Public realization char for wchar and char version 2179 */ 2180SECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream) 2181{ 2182 if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) { 2183 SECUREC_UN_GET_CHAR(stream); 2184 return; 2185 } 2186#if SECUREC_ENABLE_SCANF_FILE 2187 if ((stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) != 0) { 2188 SECUREC_UN_GET_CHAR(stream); 2189 if (stream->fileRealRead > 0) { 2190 stream->fileRealRead -= sizeof(SecChar); 2191 } 2192 return; 2193 } 2194 if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) { 2195 (void)SECUREC_UN_GETC(ch, stream->pf); 2196 return; 2197 } 2198#else 2199 (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 2200#endif 2201} 2202 2203/* 2204 * Unget char for char version 2205 */ 2206SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter) 2207{ 2208 *counter = *counter - 1; /* Always minus 1 */ 2209 if (ch != SECUREC_EOF) { 2210 SecUnGetCharImpl(ch, stream); 2211 } 2212} 2213 2214/* 2215 * Skip space char by isspace 2216 */ 2217SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter) 2218{ 2219 SecInt ch; 2220 do { 2221 ch = SecGetChar(stream, counter); 2222 if (ch == SECUREC_EOF) { 2223 break; 2224 } 2225 } while (SecIsSpace(ch) != 0); 2226 return ch; 2227} 2228#endif /* INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 */ 2229 2230