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