• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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