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