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