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