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