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