1 /*
2 * Copyright (c) 2020 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 #include "stdio.h"
17 #include <stdarg.h>
18 #include <securec.h>
19 #include "fcntl.h"
20 #include "unistd.h"
21 #include <log.h>
22
23 #ifndef LOSCFG_BASE_CORE_HILOG
24 #include <stdatomic.h>
25 #include "hilog_trace.h"
26 #endif
27
28 typedef int SecInt32;
29 typedef unsigned int SecUnsignedInt32;
30 typedef long long SecInt64;
31 typedef unsigned long long SecUnsignedInt64;
32
33 #ifndef LOSCFG_BASE_CORE_HILOG
34 static RegisterFunc g_registerFunc = NULL;
35 static atomic_int g_hiLogGetIdCallCount = 0;
36 #endif
37
38 #define SECUREC_BUFFER_SIZE 256
39
40 #define SECUREC_MAX_PRECISION SECUREC_BUFFER_SIZE
41 /* max. # bytes in multibyte char ,see MB_LEN_MAX */
42 #define SECUREC_MB_LEN 16
43
44 /* state definitions */
45 #define SECUREC_FLAG_SIGN 0x00001U
46 #define SECUREC_FLAG_SIGN_SPACE 0x00002U
47 #define SECUREC_FLAG_LEFT 0x00004U
48 #define SECUREC_FLAG_LEADZERO 0x00008U
49 #define SECUREC_FLAG_LONG 0x00010U
50 #define SECUREC_FLAG_SHORT 0x00020U
51 #define SECUREC_FLAG_SIGNED 0x00040U
52 #define SECUREC_FLAG_ALTERNATE 0x00080U
53 #define SECUREC_FLAG_NEGATIVE 0x00100U
54 #define SECUREC_FLAG_FORCE_OCTAL 0x00200U
55 #define SECUREC_FLAG_LONG_DOUBLE 0x00400U
56 #define SECUREC_FLAG_WIDECHAR 0x00800U
57 #define SECUREC_FLAG_LONGLONG 0x01000U
58 #define SECUREC_FLAG_CHAR 0x02000U
59 #define SECUREC_FLAG_POINTER 0x04000U
60 #define SECUREC_FLAG_I64 0x08000U
61 #define SECUREC_FLAG_PTRDIFF 0x10000U
62 #define SECUREC_FLAG_SIZE 0x20000U
63 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
64 #define SECUREC_FLAG_INTMAX 0x40000U
65 #endif
66
67
68 typedef enum {
69 STAT_NORMAL,
70 STAT_PERCENT,
71 STAT_FLAG,
72 STAT_WIDTH,
73 STAT_DOT,
74 STAT_PRECIS,
75 STAT_SIZE,
76 STAT_TYPE,
77 STAT_INVALID
78 } SecFmtState;
79
80 #define SECUREC_PRINTF_TRUNCATE (-2)
81 typedef struct {
82 int count;
83 char *cur;
84 } SecPrintfStream;
85 #define SECUREC_ERROR_INVALID_PARAMTER(msg) printf("%s invalid argument\n", msg)
86 #define SECUREC_ERROR_INVALID_RANGE(msg) printf("%s invalid dest buffer size\n", msg)
87 #define SECUREC_ERROR_BUFFER_OVERLAP(msg) printf("%s buffer overlap\n", msg)
88
89 // Log type
90 #define LOG_BUF_SIZE (1024)
91 #define MAX_DOMAIN_TAG_SIZE 64
92 #define IOV_SIZE (3)
93 #define HILOG_IOV_SIZE 4
94 #define HITRACE_BUF_SIZE 128
95 #define MAX_INIT_RETRIES (500)
96 #define DOMAIN_MIN 0x0D000000
97 #define DOMAIN_MAX 0x0E000000
98
99 #define SECUREC_FLOAT_BUFSIZE (309 + 40) /* max float point value */
100 #define SECUREC_FLOAT_BUFSIZE_LB (4932 + 40) /* max long double value */
101
102 #define SECUREC_INT_MAX 2147483647
103
104 #define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1)
105 #define SECUREC_INT_MAX_DIV_TEN 21474836
106 #define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN))
107
108 #ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
109 #define SECUREC_FMT_STR_LEN (8)
110 #else
111 #define SECUREC_FMT_STR_LEN (16)
112 #endif
113
114 #ifndef SECUREC_PUTC
115 #define SECUREC_PUTC(_c, _stream) ((--(_stream)->count >= 0) ? (*(_stream)->cur++ = (char)(_c)) : EOF)
116 #endif
117 /* to clear e835 */
118 #ifndef SECUREC_PUTC_ZERO
119 #define SECUREC_PUTC_ZERO(_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)('\0'))) : EOF)
120 #endif
121
122 #ifndef SECUREC_MALLOC
123 #define SECUREC_MALLOC(x) malloc((size_t)(x))
124 #endif
125
126 #ifndef SECUREC_FREE
127 #define SECUREC_FREE(x) free((void *)(x))
128 #endif
129
130 typedef char SecChar;
131 #define SECUREC_CHAR(x) x
132 /* put a char to output */
133 #define SECUREC_PUTC(_c, _stream) ((--(_stream)->count >= 0) ? (*(_stream)->cur++ = (char)(_c)) : EOF)
134 /* to clear e835 */
135
136 #define SECUREC_PUTC_ZERO(_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)('\0'))) : EOF)
137
SecPutWcharStrEndingZero(SecPrintfStream * str,int zeroNum)138 int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroNum)
139 {
140 int succeed = 0;
141 int i;
142
143 for (i = 0; i < zeroNum && (SECUREC_PUTC_ZERO(str) != EOF); ++i) {
144 }
145 if (i == zeroNum) {
146 succeed = 1;
147 }
148 return succeed;
149 }
150
SecWriteMultiChar(char ch,int num,SecPrintfStream * f,int * pnumwritten)151 void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten)
152 {
153 int count = num;
154 while (count-- > 0) {
155 if (SECUREC_PUTC(ch, f) == EOF) {
156 *pnumwritten = -1;
157 break;
158 } else {
159 ++(*pnumwritten);
160 }
161 }
162 }
163
SecWriteString(const char * string,int len,SecPrintfStream * f,int * pnumwritten)164 void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten)
165 {
166 const char *str = string;
167 int count = len;
168 while (count-- > 0) {
169 if (SECUREC_PUTC(*str, f) == EOF) {
170 *pnumwritten = -1;
171 break;
172 } else {
173 ++(*pnumwritten);
174 ++str;
175 }
176 }
177 }
178
179 #ifndef LOSCFG_BASE_CORE_HILOG
HiLogRegisterGetIdFun(RegisterFunc registerFunc)180 int HiLogRegisterGetIdFun(RegisterFunc registerFunc)
181 {
182 if (g_registerFunc != NULL) {
183 return -1;
184 }
185 g_registerFunc = registerFunc;
186 return 0;
187 }
188
HiLogUnregisterGetIdFun(RegisterFunc registerFunc)189 void HiLogUnregisterGetIdFun(RegisterFunc registerFunc)
190 {
191 if (g_registerFunc != registerFunc) {
192 return;
193 }
194
195 g_registerFunc = NULL;
196 while (atomic_load(&g_hiLogGetIdCallCount) != 0) {
197 /* do nothing, just wait current callback return */
198 }
199
200 return;
201 }
202 #endif
203
204 #define SECUREC_WRITE_MULTI_CHAR SecWriteMultiChar
205 #define SECUREC_WRITE_STRING SecWriteString
206
207 typedef struct {
208 unsigned int flags;
209 int fldWidth;
210 int precision;
211 int bufferIsWide; /* flag for buffer contains wide chars */
212 int dynWidth; /* %* 1 width from variable parameter ;0 not */
213 int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */
214 } SecFormatAttr;
215
216 typedef union {
217 char *str; /* not a null terminated string */
218 wchar_t *wStr;
219 } SecFormatBuf;
220
221 typedef union {
222 char str[SECUREC_BUFFER_SIZE + 1];
223 #ifdef SECUREC_FOR_WCHAR
224 wchar_t wStr[SECUREC_BUFFER_SIZE + 1];
225 #endif
226 } SecBuffer;
227
228 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
229 /* to clear e506 warning */
SecIsSameSize(size_t sizeA,size_t sizeB)230 static int SecIsSameSize(size_t sizeA, size_t sizeB)
231 {
232 return sizeA == sizeB;
233 }
234 #endif
235 #define SECUREC_WHILE_ZERO while (0)
236
237 #define SECUREC_SPECIAL(_val, Base) case Base: \
238 do { \
239 *--formatBuf.str = digits[_val % Base]; \
240 } while ((_val /= Base) != 0)
241
242 #define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) \
243 do { \
244 for (ii = 0; ii < txtLen; ++ii) { \
245 *((SecChar *)(void *)(_stream->cur)) = *(src); \
246 _stream->cur += sizeof(SecChar); \
247 ++(src); \
248 } \
249 _stream->count -= txtLen * (int)(sizeof(SecChar)); \
250 *(outChars) = *(outChars) + (txtLen); \
251 } \
252 SECUREC_WHILE_ZERO
253 #define MOBILE_NUMBER_LENGTH 12
254 #define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) \
255 do { \
256 if (txtLen < MOBILE_NUMBER_LENGTH) { \
257 for (ii = 0; ii < txtLen; ++ii) { \
258 *((SecChar *)(void *)(_stream->cur)) = *(src); \
259 _stream->cur += sizeof(SecChar); \
260 ++(src); \
261 } \
262 } else { \
263 (void)memcpy_s(_stream->cur, ((size_t)(unsigned int)txtLen * (sizeof(SecChar))), src, \
264 ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \
265 _stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \
266 } \
267 _stream->count -= txtLen * (int)(sizeof(SecChar)); \
268 *(outChars) = *(outChars) + (txtLen); \
269 } \
270 SECUREC_WHILE_ZERO
271
272 #define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \
273 *((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \
274 _stream->cur += sizeof(SecChar); \
275 _stream->count -= (int)(sizeof(SecChar)); \
276 *(outChars) = *(outChars) + 1; \
277 } \
278 SECUREC_WHILE_ZERO
279
280 #define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) \
281 do { \
282 for (ii = 0; ii < padLen; ++ii) { \
283 *((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \
284 _stream->cur += sizeof(SecChar); \
285 } \
286 _stream->count -= padLen * (int)(sizeof(SecChar)); \
287 *(outChars) = *(outChars) + (padLen); \
288 } \
289 SECUREC_WHILE_ZERO
290
291 /* The count variable can be reduced to 0, and the external function complements the \0 terminator. */
292 #define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar))) >= 0)
293
294 #define SECUREC_FMT_STATE_OFFSET 256
295 #ifdef SECUREC_FOR_WCHAR
296 #define SECUREC_FMT_TYPE(c, fmtTable) \
297 ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? (fmtTable[(unsigned char)(c)]) : 0)
298 #define SECUREC_DECODE_STATE(c, fmtTable, laststate) \
299 (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c, fmtTable)) * ((unsigned char)STAT_INVALID + 1) + \
300 (unsigned char)(laststate) + SECUREC_FMT_STATE_OFFSET])))
301 #else
302 #define SECUREC_DECODE_STATE(c, fmtTable, laststate) \
303 (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * ((unsigned char)STAT_INVALID + 1) + \
304 (unsigned char)(laststate) + SECUREC_FMT_STATE_OFFSET]))
305 #endif
306
SecDecodeFlags(SecChar ch,SecFormatAttr * attr)307 static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr)
308 {
309 switch (ch) {
310 case SECUREC_CHAR(' '):
311 attr->flags |= SECUREC_FLAG_SIGN_SPACE;
312 break;
313 case SECUREC_CHAR('+'):
314 attr->flags |= SECUREC_FLAG_SIGN;
315 break;
316 case SECUREC_CHAR('-'):
317 attr->flags |= SECUREC_FLAG_LEFT;
318 break;
319 case SECUREC_CHAR('0'):
320 attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */
321 break;
322 case SECUREC_CHAR('#'):
323 attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */
324 break;
325 default:
326 break;
327 }
328 return;
329 }
330
SecDecodeSize(SecChar ch,SecFormatAttr * attr,const SecChar ** format)331 static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format)
332 {
333 switch (ch) {
334 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
335 case SECUREC_CHAR('j'):
336 attr->flags |= SECUREC_FLAG_INTMAX;
337 break;
338 #endif
339 case SECUREC_CHAR('q'): /* fall-through */ /* FALLTHRU */
340 case SECUREC_CHAR('L'):
341 attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE;
342 break;
343 case SECUREC_CHAR('l'):
344 if (**format == SECUREC_CHAR('l')) {
345 ++(*format);
346 attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */
347 } else {
348 attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */
349 }
350 break;
351 case SECUREC_CHAR('t'):
352 attr->flags |= SECUREC_FLAG_PTRDIFF;
353 break;
354 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
355 case SECUREC_CHAR('z'):
356 attr->flags |= SECUREC_FLAG_SIZE;
357 break;
358 case SECUREC_CHAR('Z'):
359 attr->flags |= SECUREC_FLAG_SIZE;
360 break;
361 #endif
362
363 case SECUREC_CHAR('I'):
364 #ifdef SECUREC_ON_64BITS
365 attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */
366 #endif
367 if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) {
368 (*format) += 2;
369 attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */
370 } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) {
371 (*format) += 2;
372 attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */
373 } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) ||
374 (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || (**format == SECUREC_CHAR('x')) ||
375 (**format == SECUREC_CHAR('X'))) {
376 /* do nothing */
377 } else {
378 /* Compatibility code for "%I" just print I */
379 return -1;
380 }
381 break;
382
383 case SECUREC_CHAR('h'):
384 if (**format == SECUREC_CHAR('h'))
385 attr->flags |= SECUREC_FLAG_CHAR; /* char */
386 else
387 attr->flags |= SECUREC_FLAG_SHORT; /* short int */
388 break;
389
390 case SECUREC_CHAR('w'):
391 attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */
392 break;
393 default:
394 break;
395 }
396
397 return 0;
398 }
399
SecDecodeTypeC(SecFormatAttr * attr,unsigned int cValue,SecFormatBuf * formatBuf,SecBuffer * buffer)400 static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
401 {
402 int textLen;
403 wchar_t wchar;
404
405 #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS))
406 attr->flags &= ~SECUREC_FLAG_LEADZERO;
407 #endif
408
409 #ifdef SECUREC_FOR_WCHAR
410 attr->bufferIsWide = 1;
411 wchar = (wchar_t)cValue;
412 if (attr->flags & SECUREC_FLAG_SHORT) {
413 /* multibyte character to wide character */
414 char tempchar[2];
415 tempchar[0] = (char)(wchar & 0x00ff);
416 tempchar[1] = '\0';
417
418 if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) {
419 return -1;
420 }
421 } else {
422 buffer->wStr[0] = wchar;
423 }
424 formatBuf->wStr = buffer->wStr;
425 textLen = 1; /* only 1 wide character */
426 #else
427 attr->bufferIsWide = 0;
428 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
429 wchar = (wchar_t)cValue;
430 /* wide character to multibyte character */
431 // SECUREC_MASK_MSVC_CRT_WARNING
432 textLen = wctomb(buffer->str, wchar);
433 // SECUREC_END_MASK_MSVC_CRT_WARNING
434 if (textLen < 0) {
435 return -1;
436 }
437 } else {
438 /* get multibyte character from argument */
439 unsigned short temp;
440 temp = (unsigned short)cValue;
441 buffer->str[0] = (char)temp;
442 textLen = 1;
443 }
444 formatBuf->str = buffer->str;
445 #endif
446
447 return textLen;
448 }
449
SecDecodeTypeS(SecFormatAttr * attr,char * argPtr,SecFormatBuf * formatBuf)450 static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
451 {
452 /* literal string to print null ptr, define it on stack rather than const text area
453 is to avoid gcc warning with pointing const text with variable */
454 static char strNullString[8] = "(null)";
455 static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' };
456
457 int finalPrecision;
458 char *strEnd = NULL;
459 wchar_t *wStrEnd = NULL;
460 int textLen;
461
462 #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
463 attr->flags &= ~SECUREC_FLAG_LEADZERO;
464 #endif
465 finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
466 formatBuf->str = argPtr;
467
468 #ifdef SECUREC_FOR_WCHAR
469 #if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
470 if (!(attr->flags & SECUREC_FLAG_LONG)) {
471 attr->flags |= SECUREC_FLAG_SHORT;
472 }
473 #endif
474 if (attr->flags & SECUREC_FLAG_SHORT) {
475 if (formatBuf->str == NULL) { /* NULL passed, use special string */
476 formatBuf->str = strNullString;
477 }
478 strEnd = formatBuf->str;
479 for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) {
480 ++strEnd;
481 }
482 /* textLen now contains length in multibyte chars */
483 } else {
484 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */
485 formatBuf->wStr = wStrNullString;
486 }
487 attr->bufferIsWide = 1;
488 wStrEnd = formatBuf->wStr;
489 while (finalPrecision-- && *wStrEnd) {
490 ++wStrEnd;
491 }
492 textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */
493 /* textLen now contains length in wide chars */
494 }
495 #else /* SECUREC_FOR_WCHAR */
496 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
497 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */
498 formatBuf->wStr = wStrNullString;
499 }
500 attr->bufferIsWide = 1;
501 wStrEnd = formatBuf->wStr;
502 while (finalPrecision-- && *wStrEnd) {
503 ++wStrEnd;
504 }
505 textLen = (int)(wStrEnd - formatBuf->wStr);
506 } else {
507 if (formatBuf->str == NULL) { /* meet NULL, use special string */
508 formatBuf->str = strNullString;
509 }
510
511 if (finalPrecision == SECUREC_INT_MAX) {
512 /* precision NOT assigned */
513 /* The strlen performance is high when the string length is greater than 32 */
514 textLen = (int)strlen(formatBuf->str);
515 } else {
516 /* precision assigned */
517 strEnd = formatBuf->str;
518 while (finalPrecision-- && *strEnd) {
519 ++strEnd;
520 }
521 textLen = (int)(strEnd - formatBuf->str); /* length of the string */
522 }
523 }
524
525 #endif /* SECUREC_FOR_WCHAR */
526 return textLen;
527 }
528
529 #define PUBLIC_FLAG_LEN (8)
530 #define PRIVATE_FLAG_LEN (9)
531 #define PUBLIC_FLAG "{public}"
532 #define PRIVATE_FLAG "{private}"
533 #define bool _Bool
534 static int HILOG_TRUE = 1;
535 static int HILOG_FALSE = 0;
536
HiLogSecOutputS(SecPrintfStream * stream,bool isDebugMode,const char * cformat,va_list arglist)537 int HiLogSecOutputS(SecPrintfStream *stream, bool isDebugMode, const char *cformat, va_list arglist)
538 {
539 const SecChar *format = cformat;
540
541 char *floatBuf = NULL;
542 SecFormatBuf formatBuf;
543 static const char *itoaUpperDigits = "0123456789ABCDEFX";
544 static const char *itoaLowerDigits = "0123456789abcdefx";
545 const char *digits = itoaUpperDigits;
546 int ii = 0;
547
548 unsigned int radix;
549 int charsOut; /* characters written */
550
551 int prefixLen = 0;
552 int padding = 0;
553
554 int textLen; /* length of the text */
555 int bufferSize = 0; /* size of formatBuf.str */
556 int noOutput = 0;
557
558 SecFmtState state;
559 SecFmtState laststate;
560
561 SecChar prefix[2] = { 0 };
562 SecChar ch; /* currently read character */
563 static char PRIVACY_STRING[] = "<private>";
564 static wchar_t WPRIVACY_STRING[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0'};
565 bool isPrivacy = HILOG_TRUE;
566
567 static const unsigned char fmtCharTable[337] = {
568 /* type 0: nospecial meanin;
569 1: '%';
570 2: '.'
571 3: '*'
572 4: '0'
573 5: '1' ... '9'
574 6: ' ', '+', '-', '#'
575 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
576 8: 'd','o','u','i','x','X','e','f','g'
577 */
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
581 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
583 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
585 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
586 /* fill zero for normal char 128 byte for 0x80 - 0xff */
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 /* state 0: normal
596 1: percent
597 2: flag
598 3: width
599 4: dot
600 5: precis
601 6: size
602 7: type
603 8: invalid
604 */
605 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
606 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
607 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
608 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
609 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
610 0x00
611 };
612
613 SecFormatAttr formatAttr;
614 SecBuffer buffer;
615 formatAttr.flags = 0;
616 formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */
617 formatAttr.fldWidth = 0;
618 formatAttr.precision = 0;
619 formatAttr.dynWidth = 0;
620 formatAttr.dynPrecision = 0;
621
622 charsOut = 0;
623 textLen = 0;
624 state = STAT_NORMAL; /* starting state */
625 formatBuf.str = NULL;
626
627 /* loop each format character */
628 /* remove format != NULL */
629 while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) {
630 laststate = state;
631 state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate);
632
633 switch (state) {
634 case STAT_NORMAL:
635
636 NORMAL_CHAR:
637
638 /* normal state, write character */
639 if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */)) {
640 SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */
641 } else {
642 #ifdef SECUREC_FOR_WCHAR
643 SECUREC_WRITE_CHAR(ch, stream, &charsOut);
644 #else
645 /* optimize function call to code */
646 charsOut = -1;
647 stream->count = -1;
648 #endif
649 }
650
651 continue;
652
653 case STAT_PERCENT:
654 /* set default values */
655 prefixLen = 0;
656 noOutput = 0;
657 formatAttr.flags = 0;
658 formatAttr.fldWidth = 0;
659 formatAttr.precision = -1;
660 formatAttr.bufferIsWide = 0;
661 isPrivacy = HILOG_TRUE;
662 if (0 == strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN)) {
663 isPrivacy = HILOG_FALSE;
664 format += PUBLIC_FLAG_LEN;
665 break;
666 }
667 if (0 == strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN)) {
668 isPrivacy = HILOG_TRUE;
669 format += PRIVATE_FLAG_LEN;
670 break;
671 }
672
673 if (*format == SECUREC_CHAR('%')) {
674 isPrivacy = HILOG_FALSE;
675 }
676
677 break;
678
679 case STAT_FLAG:
680 /* set flag based on which flag character */
681 SecDecodeFlags(ch, &formatAttr);
682 break;
683
684 case STAT_WIDTH:
685 /* update width value */
686 if (ch == SECUREC_CHAR('*')) {
687 /* get width */
688 formatAttr.fldWidth = (int)va_arg(arglist, int);
689 if (formatAttr.fldWidth < 0) {
690 formatAttr.flags |= SECUREC_FLAG_LEFT;
691 formatAttr.fldWidth = -formatAttr.fldWidth;
692 }
693 formatAttr.dynWidth = 1;
694 } else {
695 if (laststate != STAT_WIDTH) {
696 formatAttr.fldWidth = 0;
697 }
698 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) {
699 return -1;
700 }
701 formatAttr.fldWidth =
702 (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0'));
703 formatAttr.dynWidth = 0;
704 }
705 break;
706
707 case STAT_DOT:
708 formatAttr.precision = 0;
709 break;
710
711 case STAT_PRECIS:
712 /* update precison value */
713 if (ch == SECUREC_CHAR('*')) {
714 /* get precision from arg list */
715 formatAttr.precision = (int)va_arg(arglist, int);
716 if (formatAttr.precision < 0) {
717 formatAttr.precision = -1;
718 }
719 formatAttr.dynPrecision = 1;
720 } else {
721 /* add digit to current precision */
722 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) {
723 return -1;
724 }
725 formatAttr.precision =
726 (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0'));
727 formatAttr.dynPrecision = 0;
728 }
729 break;
730
731 case STAT_SIZE:
732 /* read a size specifier, set the formatAttr.flags based on it */
733 if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
734 /* Compatibility code for "%I" just print I */
735 state = STAT_NORMAL;
736 goto NORMAL_CHAR;
737 }
738 break;
739
740 case STAT_TYPE:
741
742 switch (ch) {
743 case SECUREC_CHAR('C'):
744 /* wide char */
745 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
746 #ifdef SECUREC_FOR_WCHAR
747 formatAttr.flags |= SECUREC_FLAG_SHORT;
748 #else
749 formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
750 #endif
751 }
752 /* fall-through */
753 /* FALLTHRU */
754 case SECUREC_CHAR('c'): {
755 unsigned int cValue = (unsigned int)va_arg(arglist, int);
756 textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
757 if (textLen < 0) {
758 noOutput = 1;
759 }
760 } break;
761 case SECUREC_CHAR('S'): /* wide char string */
762 #ifndef SECUREC_FOR_WCHAR
763 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
764 formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
765 }
766 #else
767 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
768 formatAttr.flags |= SECUREC_FLAG_SHORT;
769 }
770 #endif
771 /* fall-through */
772 /* FALLTHRU */
773 case SECUREC_CHAR('s'): {
774 char *argPtr = (char *)va_arg(arglist, char *);
775 textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
776 } break;
777
778 case SECUREC_CHAR('n'):
779 /* higher risk disable it */
780 return -1;
781
782 case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */
783 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */
784 case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */
785 case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */
786 /* convert format char to lower , use Explicit conversion to clean up compilation warning */
787 ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
788 /* fall-through */
789 /* FALLTHRU */
790 case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */
791 case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */
792 case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */
793 case SECUREC_CHAR('a'): {
794 /* floating point conversion */
795 formatBuf.str = buffer.str; /* output buffer for float string with default size */
796
797 /* compute the precision value */
798 if (formatAttr.precision < 0) {
799 formatAttr.precision = 6;
800 } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
801 formatAttr.precision = 1;
802 }
803
804 /* calc buffer size to store long double value */
805 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
806 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
807 noOutput = 1;
808 break;
809 }
810 bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
811 } else {
812 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
813 noOutput = 1;
814 break;
815 }
816 bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
817 }
818 if (formatAttr.fldWidth > bufferSize) {
819 bufferSize = formatAttr.fldWidth;
820 }
821
822 if (bufferSize >= SECUREC_BUFFER_SIZE) {
823 /* the current vlaue of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
824 /* size include '+' and '\0' */
825 floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
826 if (floatBuf != NULL) {
827 formatBuf.str = floatBuf;
828 } else {
829 noOutput = 1;
830 break;
831 }
832 }
833
834 {
835 /* add following code to call system sprintf API for float number */
836 const SecChar *pFltFmt = format - 2; /* point to the position before 'f' or 'g' */
837 int k = 0;
838 int fltFmtStrLen;
839 char fltFmtBuf[SECUREC_FMT_STR_LEN];
840 char *fltFmtStr = fltFmtBuf;
841 char *fltFmtHeap = NULL; /* to clear warning */
842
843 while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) { /* must meet '%' */
844 --pFltFmt;
845 }
846
847 fltFmtStrLen = (int)((format - pFltFmt) + 1); /* with ending terminator */
848 if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
849 /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
850 fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
851 if (fltFmtHeap == NULL) {
852 noOutput = 1;
853 break;
854 } else {
855 if (SECUREC_CHAR('%') != *pFltFmt) {
856 fltFmtHeap[0] = '%';
857 ++k;
858 }
859 for (; k < fltFmtStrLen - 1; ++k) {
860 /* convert wchar to char */
861 fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
862 }
863 fltFmtHeap[k] = '\0';
864
865 fltFmtStr = fltFmtHeap;
866 }
867 } else {
868 if (SECUREC_CHAR('%') != *pFltFmt) {
869 fltFmtBuf[0] = '%';
870 ++k;
871 }
872 /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */
873 for (; k < fltFmtStrLen - 1; ++k) {
874 /* convert wchar to char */
875 fltFmtBuf[k] = (char)(pFltFmt[k]); /* copy the format string */
876 }
877 fltFmtBuf[k] = '\0';
878 }
879
880 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
881 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
882 long double tmp = (long double)va_arg(arglist, long double);
883 /* call system sprintf to format float value */
884 if (formatAttr.dynWidth && formatAttr.dynPrecision) {
885 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
886 formatAttr.fldWidth, formatAttr.precision, tmp);
887 } else if (formatAttr.dynWidth) {
888 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
889 formatAttr.fldWidth, tmp);
890 } else if (formatAttr.dynPrecision) {
891 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
892 formatAttr.precision, tmp);
893 } else {
894 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr, tmp);
895 }
896 } else
897 #endif
898 {
899 double tmp = (double)va_arg(arglist, double);
900 if (formatAttr.dynWidth && formatAttr.dynPrecision) {
901 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
902 formatAttr.fldWidth, formatAttr.precision, tmp);
903 } else if (formatAttr.dynWidth) {
904 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
905 formatAttr.fldWidth, tmp);
906 } else if (formatAttr.dynPrecision) {
907 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr,
908 formatAttr.precision, tmp);
909 } else {
910 textLen = sprintf_s(formatBuf.str, SECUREC_BUFFER_SIZE + 1, (char *)fltFmtStr, tmp);
911 }
912 }
913
914 if (fltFmtHeap != NULL) {
915 /* if buffer is alloced on heap, free it */
916 SECUREC_FREE(fltFmtHeap);
917 fltFmtHeap = NULL;
918 }
919 if (textLen < 0) {
920 /* bufferSize is large enough,just validation the return value */
921 noOutput = 1;
922 break;
923 }
924
925 formatAttr.fldWidth =
926 textLen; /* no padding ,this variable to calculate amount of padding */
927 prefixLen = 0; /* no padding ,this variable to calculate amount of padding */
928 formatAttr.flags = 0; /* clear all internal formatAttr.flags */
929 break;
930 }
931 }
932
933 case SECUREC_CHAR('p'):
934 /* print a pointer */
935 #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
936 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
937 #else
938 formatAttr.flags |= SECUREC_FLAG_POINTER;
939 #endif
940
941 #ifdef SECUREC_ON_64BITS
942 formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */
943 #else
944 formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */
945 #endif
946
947 #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
948
949 #if defined(SECUREC_VXWORKS_PLATFORM)
950 formatAttr.precision = 1;
951 #else
952 formatAttr.precision = 0;
953 #endif
954 formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
955 digits = itoaLowerDigits;
956 goto OUTPUT_HEX;
957 #else
958 /* not linux vxwoks */
959 #if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
960 formatAttr.precision = 1;
961 #else
962 formatAttr.precision = 2 * sizeof(void *);
963 #endif
964
965 #endif
966
967 #if defined(SECUREC_ON_UNIX)
968 digits = itoaLowerDigits;
969 goto OUTPUT_HEX;
970 #endif
971
972 /* fall-through */
973 /* FALLTHRU */
974 case SECUREC_CHAR('X'):
975 /* unsigned upper hex output */
976 digits = itoaUpperDigits;
977 goto OUTPUT_HEX;
978
979 case SECUREC_CHAR('x'):
980 /* unsigned lower hex output */
981 digits = itoaLowerDigits;
982
983 OUTPUT_HEX:
984 radix = 16;
985 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
986 /* alternate form means '0x' prefix */
987 prefix[0] = SECUREC_CHAR('0');
988 prefix[1] = (SecChar)(digits[16]); /* 'x' or 'X' */
989
990 #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
991 if (ch == 'p') {
992 prefix[1] = SECUREC_CHAR('x');
993 }
994 #endif
995 #if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
996 if (ch == 'p') {
997 prefixLen = 0;
998 } else {
999 prefixLen = 2;
1000 }
1001 #else
1002 prefixLen = 2;
1003 #endif
1004 }
1005 goto OUTPUT_INT;
1006 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */
1007 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */
1008 /* signed decimal output */
1009 formatAttr.flags |= SECUREC_FLAG_SIGNED;
1010 /* fall-through */
1011 /* FALLTHRU */
1012 case SECUREC_CHAR('u'):
1013 radix = 10;
1014 goto OUTPUT_INT;
1015 case SECUREC_CHAR('o'):
1016 /* unsigned octal output */
1017 radix = 8;
1018 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
1019 /* alternate form means force a leading 0 */
1020 formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
1021 }
1022 OUTPUT_INT : {
1023 SecUnsignedInt64 number = 0; /* number to convert */
1024 SecInt64 l; /* temp long value */
1025 unsigned char tch;
1026 #if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
1027 SecUnsignedInt32 digit = 0; /* ascii value of digit */
1028 SecUnsignedInt32 quotientHigh = 0;
1029 SecUnsignedInt32 quotientLow = 0;
1030 #endif
1031
1032 /* read argument into variable l */
1033 if (formatAttr.flags & SECUREC_FLAG_I64) {
1034 l = (SecInt64)va_arg(arglist, SecInt64);
1035 } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
1036 l = (SecInt64)va_arg(arglist, SecInt64);
1037 } else
1038 #ifdef SECUREC_ON_64BITS
1039 if (formatAttr.flags & SECUREC_FLAG_LONG) {
1040 l = (long)va_arg(arglist, long);
1041 } else
1042 #endif /* SECUREC_ON_64BITS */
1043 if (formatAttr.flags & SECUREC_FLAG_CHAR) {
1044 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1045 l = (char)va_arg(arglist, int); /* sign extend */
1046 if (l >= 128) { /* on some platform, char is always unsigned */
1047 SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
1048 formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
1049 tch = (unsigned char)(~(tmpL));
1050 l = tch + 1;
1051 }
1052 } else {
1053 l = (unsigned char)va_arg(arglist, int); /* zero-extend */
1054 }
1055 } else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
1056 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1057 l = (short)va_arg(arglist, int); /* sign extend */
1058 } else {
1059 l = (unsigned short)va_arg(arglist, int); /* zero-extend */
1060 }
1061 }
1062 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1063 else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
1064 l = (ptrdiff_t)va_arg(arglist, ptrdiff_t); /* sign extend */
1065 } else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
1066 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1067 /* No suitable macros were found to handle the branch */
1068 if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
1069 l = va_arg(arglist, long); /* sign extend */
1070 } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
1071 l = va_arg(arglist, long long); /* sign extend */
1072 } else {
1073 l = va_arg(arglist, int); /* sign extend */
1074 }
1075 } else {
1076 l = (SecInt64)(size_t)va_arg(arglist, size_t); /* sign extend */
1077 }
1078 } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
1079 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1080 l = va_arg(arglist, SecInt64); /* sign extend */
1081 } else {
1082 l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64); /* sign extend */
1083 }
1084 }
1085 #endif
1086 else {
1087 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1088 l = va_arg(arglist, int); /* sign extend */
1089 } else {
1090 l = (unsigned int)va_arg(arglist, int); /* zero-extend */
1091 }
1092 }
1093
1094 /* check for negative; copy into number */
1095 if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
1096 number = (SecUnsignedInt64)(-l);
1097 formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
1098 } else {
1099 number = (SecUnsignedInt64)l;
1100 }
1101
1102 if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
1103 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1104 ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
1105 #endif
1106 #ifdef SECUREC_ON_64BITS
1107 ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
1108 ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
1109 #if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */
1110 ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
1111 #endif
1112 #endif
1113 ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
1114
1115 number &= 0xffffffff;
1116 }
1117
1118 /* check precision value for default */
1119 if (formatAttr.precision < 0) {
1120 formatAttr.precision = 1; /* default precision */
1121 } else {
1122 #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1123 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1124 #else
1125 if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
1126 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1127 }
1128 #endif
1129 if (formatAttr.precision > SECUREC_MAX_PRECISION) {
1130 formatAttr.precision = SECUREC_MAX_PRECISION;
1131 }
1132 }
1133
1134 /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */
1135 if (number == 0) {
1136 #if !(defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux))
1137 prefixLen = 0;
1138 #else
1139 if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE))
1140 prefixLen = 2;
1141 else
1142 prefixLen = 0;
1143 #endif
1144 }
1145
1146 /* Convert data to ASCII */
1147 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
1148
1149 if (number > 0) {
1150 #ifdef SECUREC_ON_64BITS
1151 switch (radix) {
1152 /* the compiler will optimize each one */
1153 SECUREC_SPECIAL(number, 10);
1154 break;
1155 SECUREC_SPECIAL(number, 16);
1156 break;
1157 SECUREC_SPECIAL(number, 8);
1158 break;
1159 default:
1160 break;
1161 }
1162 #else /* for 32 bits system */
1163 if (number <= 0xFFFFFFFFUL) {
1164 /* in most case, the value to be converted is small value */
1165 SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
1166 switch (radix) {
1167 SECUREC_SPECIAL(n32Tmp, 16);
1168 break;
1169 SECUREC_SPECIAL(n32Tmp, 8);
1170 break;
1171
1172 #ifdef _AIX
1173 /* the compiler will optimize div 10 */
1174 SECUREC_SPECIAL(n32Tmp, 10);
1175 break;
1176 #else
1177 case 10: {
1178 /* fast div 10 */
1179 SecUnsignedInt32 q;
1180 SecUnsignedInt32 r;
1181 do {
1182 *--formatBuf.str = digits[n32Tmp % 10];
1183 q = (n32Tmp >> 1) + (n32Tmp >> 2);
1184 q = q + (q >> 4);
1185 q = q + (q >> 8);
1186 q = q + (q >> 16);
1187 q = q >> 3;
1188 r = n32Tmp - (((q << 2) + q) << 1);
1189 n32Tmp = (r > 9) ? (q + 1) : q;
1190 } while (n32Tmp != 0);
1191 } break;
1192 #endif
1193 default:
1194 break;
1195 } /* end switch */
1196 } else {
1197 /* the value to be converted is greater than 4G */
1198 #if defined(SECUREC_VXWORKS_VERSION_5_4)
1199 do {
1200 if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16),
1201 (SecUnsignedInt32)number, (SecUnsignedInt32)radix, "ientHigh, "ientLow,
1202 &digit)) {
1203 noOutput = 1;
1204 break;
1205 }
1206 *--formatBuf.str = digits[digit];
1207
1208 number = (SecUnsignedInt64)quotientHigh;
1209 number = (number << 32) + quotientLow;
1210 } while (number != 0);
1211 #else
1212 switch (radix) {
1213 /* the compiler will optimize div 10 */
1214 SECUREC_SPECIAL(number, 10);
1215 break;
1216 SECUREC_SPECIAL(number, 16);
1217 break;
1218 SECUREC_SPECIAL(number, 8);
1219 break;
1220 default:
1221 break;
1222 }
1223 #endif
1224 }
1225 #endif
1226 } /* END if (number > 0) */
1227 /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
1228 textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
1229 if (formatAttr.precision > textLen) {
1230 for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
1231 *--formatBuf.str = '0';
1232 }
1233 textLen = formatAttr.precision;
1234 }
1235
1236 /* Force a leading zero if FORCEOCTAL flag set */
1237 if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) &&
1238 (textLen == 0 || formatBuf.str[0] != '0')) {
1239 *--formatBuf.str = '0';
1240 ++textLen; /* add a zero */
1241 }
1242 } break;
1243 default:
1244 break;
1245 }
1246
1247 if (noOutput == 0) {
1248 if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1249 if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
1250 /* prefix is a '-' */
1251 prefix[0] = SECUREC_CHAR('-');
1252 prefixLen = 1;
1253 } else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
1254 /* prefix is '+' */
1255 prefix[0] = SECUREC_CHAR('+');
1256 prefixLen = 1;
1257 } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
1258 /* prefix is ' ' */
1259 prefix[0] = SECUREC_CHAR(' ');
1260 prefixLen = 1;
1261 }
1262 }
1263
1264 #if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
1265 if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) {
1266 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1267 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
1268 *formatBuf.str-- = '\0';
1269 *formatBuf.str-- = ')';
1270 *formatBuf.str-- = 'l';
1271 *formatBuf.str-- = 'i';
1272 *formatBuf.str-- = 'n';
1273 *formatBuf.str = '(';
1274 textLen = 5;
1275 }
1276 #endif
1277
1278 /* calculate amount of padding */
1279 padding = (formatAttr.fldWidth - textLen) - prefixLen;
1280
1281 /* put out the padding, prefix, and text, in the correct order */
1282
1283 if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
1284 /* pad on left with blanks */
1285 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1286 /* char * cast to wchar * */
1287 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1288 } else {
1289 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1290 }
1291 }
1292
1293
1294 /* write prefix */
1295 if (prefixLen > 0) {
1296 SecChar *pPrefix = prefix;
1297 if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) {
1298 /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */
1299 SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut);
1300 } else {
1301 SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
1302 }
1303 }
1304
1305 if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) &&
1306 padding > 0) {
1307 /* write leading zeros */
1308 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1309 /* char * cast to wchar * */
1310 SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
1311 } else {
1312 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
1313 }
1314 }
1315
1316 /* write text */
1317 #ifndef SECUREC_FOR_WCHAR
1318 if (!isDebugMode && isPrivacy) {
1319 if (formatAttr.bufferIsWide) {
1320 formatBuf.wStr = WPRIVACY_STRING;
1321 textLen = sizeof(WPRIVACY_STRING) / sizeof(wchar_t) - 1;
1322 } else {
1323 formatBuf.str = PRIVACY_STRING;
1324 textLen = strlen(PRIVACY_STRING);
1325 }
1326 }
1327 if (formatAttr.bufferIsWide && (textLen > 0)) {
1328 wchar_t *p = formatBuf.wStr;
1329 int count = textLen;
1330 while (count--) {
1331 char tmpBuf[SECUREC_MB_LEN + 1];
1332 // SECUREC_MASK_MSVC_CRT_WARNING
1333 int retVal = wctomb(tmpBuf, *p++);
1334 // SECUREC_END_MASK_MSVC_CRT_WARNING
1335 if (retVal <= 0) {
1336 charsOut = -1;
1337 break;
1338 }
1339 SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
1340 }
1341 } else {
1342 if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1343 SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
1344 } else {
1345 SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
1346 }
1347 }
1348 #else /* SECUREC_FOR_WCHAR */
1349 if (formatAttr.bufferIsWide == 0 && textLen > 0) {
1350 int count = textLen;
1351 char *p = formatBuf.str;
1352
1353 while (count > 0) {
1354 wchar_t wchar = L'\0';
1355 int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX);
1356 if (retVal <= 0) {
1357 charsOut = -1;
1358 break;
1359 }
1360 SECUREC_WRITE_CHAR(wchar, stream, &charsOut);
1361 p += retVal;
1362 count -= retVal;
1363 }
1364 } else {
1365 if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1366 SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream,
1367 &charsOut); /* char * cast to wchar * */
1368 } else {
1369 SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
1370 }
1371 }
1372 #endif /* SECUREC_FOR_WCHAR */
1373
1374 if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
1375 /* pad on right with blanks */
1376 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1377 /* char * cast to wchar * */
1378 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1379 } else {
1380 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1381 }
1382 }
1383
1384 /* we're done! */
1385 }
1386 if (floatBuf != NULL) {
1387 SECUREC_FREE(floatBuf);
1388 floatBuf = NULL;
1389 }
1390 break;
1391 case STAT_INVALID:
1392 return -1;
1393 default:
1394 return -1; /* input format is wrong, directly return */
1395 }
1396 }
1397
1398 if (state != STAT_NORMAL && state != STAT_TYPE) {
1399 return -1;
1400 }
1401
1402 return charsOut; /* the number of characters written */
1403 } /* arglist must not be declare as const */
1404
1405
HiLogSecVsnprintfImpl(char * string,size_t count,bool isDebugMode,const char * format,va_list arglist)1406 int HiLogSecVsnprintfImpl(char *string, size_t count, bool isDebugMode, const char *format, va_list arglist)
1407 {
1408 SecPrintfStream str;
1409 int retVal;
1410
1411 str.count = (int)count; /* this count include \0 character */
1412 str.cur = string;
1413
1414 retVal = HiLogSecOutputS(&str, isDebugMode, format, arglist);
1415 if ((retVal >= 0) && (SECUREC_PUTC_ZERO(&str) != EOF)) {
1416 return (retVal);
1417 } else if (str.count < 0) {
1418 /* the buffer was too small; we return truncation */
1419 string[count - 1] = 0;
1420 return SECUREC_PRINTF_TRUNCATE;
1421 }
1422
1423 return -1;
1424 }
1425
1426
HiLog_Printf(char * strDest,size_t destMax,size_t count,bool isDebugMode,const char * format,va_list arglist)1427 int HiLog_Printf(char *strDest, size_t destMax, size_t count, bool isDebugMode, const char *format, va_list arglist)
1428 {
1429 int retVal;
1430
1431 if (format == NULL || strDest == NULL || destMax == 0 || destMax > SECUREC_STRING_MAX_LEN ||
1432 (count > (SECUREC_STRING_MAX_LEN - 1) && count != (size_t)-1)) {
1433 if (strDest != NULL && destMax > 0) {
1434 strDest[0] = '\0';
1435 }
1436 SECUREC_ERROR_INVALID_PARAMTER("hilog_printf");
1437 return -1;
1438 }
1439
1440 if (destMax > count) {
1441 retVal = HiLogSecVsnprintfImpl(strDest, count + 1, isDebugMode, format, arglist);
1442 if (retVal == SECUREC_PRINTF_TRUNCATE) { /* lsd add to keep dest buffer not destroyed 2014.2.18 */
1443 /* the string has been truncated, return -1 */
1444 return -1; /* to skip error handler, return strlen(strDest) or -1 */
1445 }
1446 } else { /* destMax <= count */
1447 retVal = HiLogSecVsnprintfImpl(strDest, destMax, isDebugMode, format, arglist);
1448 #ifdef SECUREC_COMPATIBLE_WIN_FORMAT
1449 if (retVal == SECUREC_PRINTF_TRUNCATE && count == (size_t)-1) {
1450 return -1;
1451 }
1452 #endif
1453 }
1454
1455 if (retVal < 0) {
1456 strDest[0] = '\0'; /* empty the dest strDest */
1457
1458 if (retVal == SECUREC_PRINTF_TRUNCATE) {
1459 /* Buffer too small */
1460 SECUREC_ERROR_INVALID_RANGE("hilog_printf");
1461 }
1462
1463 SECUREC_ERROR_INVALID_PARAMTER("hilog_printf");
1464 return -1;
1465 }
1466
1467 return retVal;
1468 }
1469
1470 #define HILOG_DRIVER "/dev/hilog"
1471 static char g_logLevelInfo[HILOG_LEVEL_MAX] = {
1472 'N', // "NONE"
1473 'N', // "NONE"
1474 'N', // "NONE"
1475 'D', // "DEBUG"
1476 'I', // "INFO"
1477 'W', // "WARN"
1478 'E', // "ERROR"
1479 'F' // "FATAL"
1480 };
1481
1482 #ifdef LOSCFG_BASE_CORE_HILOG
1483 extern int HiLogWriteInternal(const char *buffer, size_t bufLen);
1484 #else
1485 static int g_hilogFd = -1;
1486 #endif
1487
HiLogPrintArgs(LogType bufID,LogLevel prio,unsigned int domain,const char * tag,const char * fmt,va_list ap)1488 int HiLogPrintArgs(LogType bufID, LogLevel prio, unsigned int domain, const char *tag, const char *fmt, va_list ap)
1489 {
1490 int ret;
1491 char buf[LOG_BUF_SIZE] = {0};
1492 bool isDebugMode = 1;
1493 unsigned int bufLen;
1494
1495 #ifdef OHOS_RELEASE
1496 isDebugMode = 0;
1497 #endif
1498 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%c %05X/%s: ", g_logLevelInfo[prio], (domain & DOMAIN_FILTER),
1499 tag) == -1) {
1500 return 0;
1501 }
1502
1503 bufLen = strlen(buf);
1504 if (bufLen >= MAX_DOMAIN_TAG_SIZE) {
1505 return 0;
1506 }
1507
1508 #ifndef LOSCFG_BASE_CORE_HILOG
1509 /* print traceid */
1510 if (g_registerFunc != NULL) {
1511 char *logBuf = buf;
1512 int traceBufLen = 0;
1513 uint64_t chainId = 0;
1514 uint32_t flag = 0;
1515 uint64_t spanId = 0;
1516 uint64_t parentSpanId = 0;
1517 int ret = -1; /* default value -1: invalid trace id */
1518 atomic_fetch_add_explicit(&g_hiLogGetIdCallCount, 1, memory_order_relaxed);
1519 RegisterFunc func = g_registerFunc;
1520 if (g_registerFunc != NULL) {
1521 ret = func(&chainId, &flag, &spanId, &parentSpanId);
1522 }
1523 atomic_fetch_sub_explicit(&g_hiLogGetIdCallCount, 1, memory_order_relaxed);
1524 if (ret == 0) { /* 0: trace id with span id */
1525 traceBufLen = snprintf_s(logBuf, LOG_BUF_SIZE, LOG_BUF_SIZE - 1, "[%llx, %llx, %llx] ",
1526 (unsigned long long)chainId, (unsigned long long)spanId, (unsigned long long)parentSpanId);
1527 } else if (ret != -1) { /* trace id without span id, -1: invalid trace id */
1528 traceBufLen = snprintf_s(logBuf, LOG_BUF_SIZE, LOG_BUF_SIZE - 1, "[%llx] ",
1529 (unsigned long long)chainId);
1530 }
1531 if (traceBufLen > 0) {
1532 logBuf += traceBufLen;
1533 } else {
1534 traceBufLen = 0;
1535 }
1536 }
1537 #endif
1538
1539 HiLog_Printf(buf + bufLen, LOG_BUF_SIZE - bufLen, LOG_BUF_SIZE - bufLen - 1, isDebugMode, fmt, ap);
1540
1541 #ifdef LOSCFG_BASE_CORE_HILOG
1542 ret = HiLogWriteInternal(buf, strlen(buf) + 1);
1543 #else
1544 if (g_hilogFd == -1) {
1545 g_hilogFd = open(HILOG_DRIVER, O_WRONLY | O_CLOEXEC);
1546 }
1547 if (g_hilogFd == -1) {
1548 return 0;
1549 }
1550 ret = write(g_hilogFd, buf, strlen(buf) + 1);
1551 #endif
1552 return ret;
1553 }
1554
HiLogPrint(LogType bufID,LogLevel prio,unsigned int domain,const char * tag,const char * fmt,...)1555 int HiLogPrint(LogType bufID, LogLevel prio, unsigned int domain, const char *tag, const char *fmt, ...)
1556 {
1557 int ret;
1558 va_list ap;
1559 va_start(ap, fmt);
1560 ret = HiLogPrintArgs(bufID, prio, domain, tag, fmt, ap);
1561 va_end(ap);
1562 return ret;
1563 }
1564
FlushHilog(void)1565 int FlushHilog(void)
1566 {
1567 int ret;
1568 #define FLUSH_LOG_WRITE_LEN 3
1569 char buf[FLUSH_LOG_WRITE_LEN] = {0x07, 0x07, '\0'};
1570 #ifdef LOSCFG_BASE_CORE_HILOG
1571 ret = HiLogWriteInternal(buf, strlen(buf) + 1);
1572 #else
1573 if (g_hilogFd == -1) {
1574 g_hilogFd = open(HILOG_DRIVER, O_WRONLY);
1575 }
1576 if (g_hilogFd == -1) {
1577 return 0;
1578 }
1579 ret = write(g_hilogFd, buf, strlen(buf) + 1);
1580 #endif
1581 return ret;
1582 }