1/* 2 * Copyright (c) 2021 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 17/* [Standardize-exceptions] Use unsafe function: Portability 18 * [reason] Use unsafe function to implement security function to maintain platform compatibility. 19 * And sufficient input validation is performed before calling 20 */ 21 22#ifndef OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 23#define OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 24 25#define SECUREC_FLOAT_BUFSIZE (309+40) /* max float point value */ 26#define SECUREC_FLOAT_BUFSIZE_LB (4932+40) /* max long double value */ 27 28#define SECUREC_INT_MAX 2147483647 29 30#define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1) 31#define SECUREC_INT_MAX_DIV_TEN 21474836 32#define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN)) 33 34#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K 35#define SECUREC_FMT_STR_LEN (8) 36#else 37#define SECUREC_FMT_STR_LEN (16) 38#endif 39 40typedef struct { 41 unsigned int flags; 42 int fldWidth; 43 int precision; 44 int bufferIsWide; /* flag for buffer contains wide chars */ 45 int dynWidth; /* %* 1 width from variable parameter ;0 not */ 46 int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ 47} SecFormatAttr; 48 49typedef union { 50 char *str; /* not a null terminated string */ 51 wchar_t *wStr; 52} SecFormatBuf; 53 54typedef union { 55 char str[SECUREC_BUFFER_SIZE + 1]; 56#ifdef SECUREC_FOR_WCHAR 57 wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; 58#endif 59} SecBuffer; 60 61static int SecIndirectSprintf(char *strDest, const char *format, ...) 62{ 63 int ret; /* If initialization causes e838 */ 64 va_list arglist; 65 66 va_start(arglist, format); 67 SECUREC_MASK_MSVC_CRT_WARNING 68 ret = vsprintf(strDest, format, arglist); 69 SECUREC_END_MASK_MSVC_CRT_WARNING 70 va_end(arglist); 71 (void)arglist; /* to clear e438 last value assigned not used , the compiler will optimize this code */ 72 73 return ret; 74} 75 76#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 77/* to clear e506 warning */ 78static int SecIsSameSize(size_t sizeA, size_t sizeB) 79{ 80 return sizeA == sizeB; 81} 82#endif 83 84#define SECUREC_SPECIAL(_val, Base) \ 85 case Base: \ 86 do { \ 87 *--formatBuf.str = digits[_val % Base]; \ 88 }while ((_val /= Base) != 0) 89 90#define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) do { \ 91 for (ii = 0; ii < txtLen; ++ii) { \ 92 *((SecChar *)(void *)(_stream->cur)) = *(src); \ 93 _stream->cur += sizeof(SecChar); \ 94 ++(src); \ 95 } \ 96 _stream->count -= txtLen * (int)(sizeof(SecChar)); \ 97 *(outChars) = *(outChars) + (txtLen); \ 98 } SECUREC_WHILE_ZERO 99 100#define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) do { \ 101 if (txtLen < 12 /* for mobile number length */) { \ 102 for (ii = 0; ii < txtLen; ++ii) { \ 103 *((SecChar *)(void *)(_stream->cur)) = *(src); \ 104 _stream->cur += sizeof(SecChar); \ 105 ++(src); \ 106 } \ 107 } else { \ 108 (void)memcpy(_stream->cur, src, ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \ 109 _stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \ 110 } \ 111 _stream->count -= txtLen * (int)(sizeof(SecChar)); \ 112 *(outChars) = *(outChars) + (txtLen); \ 113 } SECUREC_WHILE_ZERO 114 115#define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \ 116 *((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \ 117 _stream->cur += sizeof(SecChar); \ 118 _stream->count -= (int)(sizeof(SecChar)); \ 119 *(outChars) = *(outChars) + 1; \ 120 } SECUREC_WHILE_ZERO 121 122#define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) do { \ 123 for (ii = 0; ii < padLen; ++ii) { \ 124 *((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \ 125 _stream->cur += sizeof(SecChar); \ 126 } \ 127 _stream->count -= padLen * (int)(sizeof(SecChar)); \ 128 *(outChars) = *(outChars) + (padLen); \ 129 } SECUREC_WHILE_ZERO 130 131/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ 132#define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar))) >= 0) 133 134#define SECUREC_FMT_STATE_OFFSET 256 135#ifdef SECUREC_FOR_WCHAR 136#define SECUREC_FMT_TYPE(c,fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ 137 (fmtTable[(unsigned char)(c)]) : 0) 138#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c,fmtTable)) * \ 139 ((unsigned char)STAT_INVALID + 1) + \ 140 (unsigned char)(laststate) + \ 141 SECUREC_FMT_STATE_OFFSET]))) 142#else 143#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * \ 144 ((unsigned char)STAT_INVALID + 1) + \ 145 (unsigned char)(laststate) + \ 146 SECUREC_FMT_STATE_OFFSET])) 147#endif 148 149#define PUBLIC_FLAG_LEN 8 150#define PRIVATE_FLAG_LEN 9 151#define PUBLIC_FLAG "{public}" 152#define PRIVATE_FLAG "{private}" 153 154static void SecWritePrivateStr(SecPrintfStream *stream, int *pCharsOut) 155{ 156 int ii = 0; 157#define PRIVATE_STR_LEN (9) 158#ifndef SECUREC_FOR_WCHAR 159 static const char privacyString[] = "<private>"; 160 const char *pPrivStr = privacyString; 161 162 if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { 163 SECUREC_SAFE_WRITE_STR(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 164 } else { 165 SECUREC_WRITE_STRING(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 166 } 167#else 168 static const wchar_t wprivacyString[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0' }; 169 const wchar_t *pwPrivStr = wprivacyString; 170 171 if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { 172 SECUREC_SAFE_WRITE_STR(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 173 } else { 174 SECUREC_WRITE_STRING(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 175 } 176#endif 177} 178 179static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) 180{ 181 switch (ch) { 182 case SECUREC_CHAR(' '): 183 attr->flags |= SECUREC_FLAG_SIGN_SPACE; 184 break; 185 case SECUREC_CHAR('+'): 186 attr->flags |= SECUREC_FLAG_SIGN; 187 break; 188 case SECUREC_CHAR('-'): 189 attr->flags |= SECUREC_FLAG_LEFT; 190 break; 191 case SECUREC_CHAR('0'): 192 attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ 193 break; 194 case SECUREC_CHAR('#'): 195 attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ 196 break; 197 default: 198 break; 199 } 200 return; 201} 202 203static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) 204{ 205 switch (ch) { 206#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 207 case SECUREC_CHAR('j'): 208 attr->flags |= SECUREC_FLAG_INTMAX; 209 break; 210#endif 211 case SECUREC_CHAR('q'): [[fallthrough]]; 212 case SECUREC_CHAR('L'): 213 attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; 214 break; 215 case SECUREC_CHAR('l'): 216 if (**format == SECUREC_CHAR('l')) { 217 ++(*format); 218 attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ 219 } else { 220 attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ 221 } 222 break; 223 case SECUREC_CHAR('t'): 224 attr->flags |= SECUREC_FLAG_PTRDIFF; 225 break; 226#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 227 case SECUREC_CHAR('z'): 228 attr->flags |= SECUREC_FLAG_SIZE; 229 break; 230 case SECUREC_CHAR('Z'): 231 attr->flags |= SECUREC_FLAG_SIZE; 232 break; 233#endif 234 235 case SECUREC_CHAR('I'): 236#ifdef SECUREC_ON_64BITS 237 attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ 238#endif 239 if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { 240 (*format) += 2; 241 attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ 242 } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { 243 (*format) += 2; 244 attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ 245 } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || 246 (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || 247 (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { 248 /* do nothing */ 249 } else { 250 /* Compatibility code for "%I" just print I */ 251 return -1; 252 } 253 break; 254 255 case SECUREC_CHAR('h'): 256 if (**format == SECUREC_CHAR('h')) 257 attr->flags |= SECUREC_FLAG_CHAR; /* char */ 258 else 259 attr->flags |= SECUREC_FLAG_SHORT; /* short int */ 260 break; 261 262 case SECUREC_CHAR('w'): 263 attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ 264 break; 265 default: 266 break; 267 268 } 269 270 return 0; 271} 272 273static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) 274{ 275 int textLen; 276 wchar_t wchar; 277 278#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) 279 attr->flags &= ~SECUREC_FLAG_LEADZERO; 280#endif 281 282#ifdef SECUREC_FOR_WCHAR 283 attr->bufferIsWide = 1; 284 wchar = (wchar_t)cValue; 285 if (attr->flags & SECUREC_FLAG_SHORT) { 286 /* multibyte character to wide character */ 287 char tempchar[2]; 288 tempchar[0] = (char)(wchar & 0x00ff); 289 tempchar[1] = '\0'; 290 291 if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) { 292 return -1; 293 } 294 } else { 295 buffer->wStr[0] = wchar; 296 } 297 formatBuf->wStr = buffer->wStr; 298 textLen = 1; /* only 1 wide character */ 299#else 300 attr->bufferIsWide = 0; 301 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 302 wchar = (wchar_t)cValue; 303 /* wide character to multibyte character */ 304 SECUREC_MASK_MSVC_CRT_WARNING 305 textLen = wctomb(buffer->str, wchar); 306 SECUREC_END_MASK_MSVC_CRT_WARNING 307 if (textLen < 0) { 308 return -1; 309 } 310 } else { 311 /* get multibyte character from argument */ 312 unsigned short temp; 313 temp = (unsigned short)cValue; 314 buffer->str[0] = (char)temp; 315 textLen = 1; 316 } 317 formatBuf->str = buffer->str; 318#endif 319 320 return textLen; 321} 322 323static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) 324{ 325 /* literal string to print null ptr, define it on stack rather than const text area 326 is to avoid gcc warning with pointing const text with variable */ 327 static char strNullString[8] = "(null)"; 328 static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; 329 330 int finalPrecision; 331 char *strEnd = NULL; 332 wchar_t *wStrEnd = NULL; 333 int textLen; 334 335#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) 336 attr->flags &= ~SECUREC_FLAG_LEADZERO; 337#endif 338 finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; 339 formatBuf->str = argPtr; 340 341#ifdef SECUREC_FOR_WCHAR 342#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) 343 if (!(attr->flags & SECUREC_FLAG_LONG)) { 344 attr->flags |= SECUREC_FLAG_SHORT; 345 } 346#endif 347 if (attr->flags & SECUREC_FLAG_SHORT) { 348 if (formatBuf->str == NULL) { /* NULL passed, use special string */ 349 formatBuf->str = strNullString; 350 } 351 strEnd = formatBuf->str; 352 for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) { 353 ++strEnd; 354 } 355 /* textLen now contains length in multibyte chars */ 356 } else { 357 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ 358 formatBuf->wStr = wStrNullString; 359 } 360 attr->bufferIsWide = 1; 361 wStrEnd = formatBuf->wStr; 362 while (finalPrecision-- && *wStrEnd) { 363 ++wStrEnd; 364 } 365 textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */ 366 /* textLen now contains length in wide chars */ 367 } 368#else /* SECUREC_FOR_WCHAR */ 369 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 370 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ 371 formatBuf->wStr = wStrNullString; 372 } 373 attr->bufferIsWide = 1; 374 wStrEnd = formatBuf->wStr; 375 while (finalPrecision-- && *wStrEnd) { 376 ++wStrEnd; 377 } 378 textLen = (int)(wStrEnd - formatBuf->wStr); 379 } else { 380 if (formatBuf->str == NULL) { /* meet NULL, use special string */ 381 formatBuf->str = strNullString; 382 } 383 384 if (finalPrecision == SECUREC_INT_MAX) { 385 /* precision NOT assigned */ 386 /* The strlen performance is high when the string length is greater than 32 */ 387 textLen = (int)strlen(formatBuf->str); 388 } else { 389 /* precision assigned */ 390 strEnd = formatBuf->str; 391 while (finalPrecision-- && *strEnd) { 392 ++strEnd; 393 } 394 textLen = (int)(strEnd - formatBuf->str); /* length of the string */ 395 } 396 397 } 398 399#endif /* SECUREC_FOR_WCHAR */ 400 return textLen; 401} 402 403HILOG_LOCAL_API 404int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist) 405{ 406 const SecChar *format = cformat; 407 408 char *floatBuf = NULL; 409 SecFormatBuf formatBuf; 410 static const char *itoaUpperDigits = "0123456789ABCDEFX"; 411 static const char *itoaLowerDigits = "0123456789abcdefx"; 412 const char *digits = itoaUpperDigits; 413 int ii = 0; 414 415 unsigned int radix; 416 int charsOut; /* characters written */ 417 418 int prefixLen = 0; 419 int padding = 0; 420 421 int textLen; /* length of the text */ 422 int bufferSize = 0; /* size of formatBuf.str */ 423 int noOutput = 0; 424 425 SecFmtState state; 426 SecFmtState laststate; 427 428 SecChar prefix[2] = { 0 }; 429 SecChar ch; /* currently read character */ 430 431 static const unsigned char fmtCharTable[337] = { 432 /* type 0: nospecial meaning; 433 1: '%'; 434 2: '.' 435 3: '*' 436 4: '0' 437 5: '1' ... '9' 438 6: ' ', '+', '-', '#' 439 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' 440 8: 'd','o','u','i','x','X','e','f','g' 441 */ 442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 444 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, 445 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 446 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 447 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 448 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, 449 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 450 /* fill zero for normal char 128 byte for 0x80 - 0xff */ 451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 459 /* state 0: normal 460 1: percent 461 2: flag 462 3: width 463 4: dot 464 5: precis 465 6: size 466 7: type 467 8: invalid 468 */ 469 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 470 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, 471 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 472 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 473 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 474 0x00 475 }; 476 477 SecFormatAttr formatAttr; 478 SecBuffer buffer; 479 formatAttr.flags = 0; 480 formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ 481 formatAttr.fldWidth = 0; 482 formatAttr.precision = 0; 483 formatAttr.dynWidth = 0; 484 formatAttr.dynPrecision = 0; 485 486 charsOut = 0; 487 textLen = 0; 488 state = STAT_NORMAL; /* starting state */ 489 formatBuf.str = NULL; 490 491 int isPrivacy = 1; /*whether show private string*/ 492 493 /* loop each format character */ 494 /* remove format != NULL */ 495 while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) { 496 laststate = state; 497 state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate); 498 499 switch (state) { 500 case STAT_NORMAL: 501 502NORMAL_CHAR: 503 504 /* normal state, write character */ 505 if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) { 506 SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */ 507 } else { 508#ifdef SECUREC_FOR_WCHAR 509 SECUREC_WRITE_CHAR(ch, stream, &charsOut); 510#else 511 /* optimize function call to code */ 512 charsOut = -1; 513 stream->count = -1; 514#endif 515 } 516 517 continue; 518 519 case STAT_PERCENT: 520 /* set default values */ 521 prefixLen = 0; 522 noOutput = 0; 523 formatAttr.flags = 0; 524 formatAttr.fldWidth = 0; 525 formatAttr.precision = -1; 526 formatAttr.bufferIsWide = 0; 527 if (*format == SECUREC_CHAR('{')) { 528 if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) { 529 isPrivacy = 0; 530 format += PUBLIC_FLAG_LEN; 531 } 532 else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) { 533 isPrivacy = 1; 534 format += PRIVATE_FLAG_LEN; 535 } 536 } 537 else { 538 isPrivacy = 1; 539 } 540 541 if (0 == priv) { 542 isPrivacy = 0; 543 } 544 545 break; 546 547 case STAT_FLAG: 548 /* set flag based on which flag character */ 549 SecDecodeFlags(ch, &formatAttr); 550 break; 551 552 case STAT_WIDTH: 553 /* update width value */ 554 if (ch == SECUREC_CHAR('*')) { 555 /* get width */ 556 formatAttr.fldWidth = (int)va_arg(arglist, int); 557 if (formatAttr.fldWidth < 0) { 558 formatAttr.flags |= SECUREC_FLAG_LEFT; 559 formatAttr.fldWidth = -formatAttr.fldWidth; 560 } 561 formatAttr.dynWidth = 1; 562 } else { 563 if (laststate != STAT_WIDTH) { 564 formatAttr.fldWidth = 0; 565 } 566 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) { 567 return -1; 568 } 569 formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0')); 570 formatAttr.dynWidth = 0; 571 } 572 break; 573 574 case STAT_DOT: 575 formatAttr.precision = 0; 576 break; 577 578 case STAT_PRECIS: 579 /* update precision value */ 580 if (ch == SECUREC_CHAR('*')) { 581 /* get precision from arg list */ 582 formatAttr.precision = (int)va_arg(arglist, int); 583 if (formatAttr.precision < 0) { 584 formatAttr.precision = -1; 585 } 586 formatAttr.dynPrecision = 1; 587 } else { 588 /* add digit to current precision */ 589 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) { 590 return -1; 591 } 592 formatAttr.precision = 593 (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0')); 594 formatAttr.dynPrecision = 0; 595 } 596 break; 597 598 case STAT_SIZE: 599 /* read a size specifier, set the formatAttr.flags based on it */ 600 if (SecDecodeSize(ch, &formatAttr, &format) != 0) { 601 /* Compatibility code for "%I" just print I */ 602 state = STAT_NORMAL; 603 goto NORMAL_CHAR; 604 } 605 break; 606 607 case STAT_TYPE: 608 609 switch (ch) { 610 611 case SECUREC_CHAR('C'): 612 /* wide char */ 613 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 614 615#ifdef SECUREC_FOR_WCHAR 616 formatAttr.flags |= SECUREC_FLAG_SHORT; 617#else 618 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 619#endif 620 } 621 [[fallthrough]]; 622 case SECUREC_CHAR('c'): 623 { 624 unsigned int cValue = (unsigned int)va_arg(arglist, int); 625 /*if it's a private arg, just write <priate> to stream*/ 626 if (isPrivacy == 1) { 627 break; 628 } 629 textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); 630 if (textLen < 0) { 631 noOutput = 1; 632 } 633 } 634 break; 635 case SECUREC_CHAR('S'): /* wide char string */ 636#ifndef SECUREC_FOR_WCHAR 637 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 638 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 639 } 640#else 641 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 642 formatAttr.flags |= SECUREC_FLAG_SHORT; 643 } 644#endif 645 [[fallthrough]]; 646 case SECUREC_CHAR('s'): 647 { 648 char *argPtr = (char *)va_arg(arglist, char *); 649 /*if it's a private arg, just write <priate> to stream*/ 650 if (isPrivacy == 1) { 651 break; 652 } 653 textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); 654 } 655 break; 656 657 case SECUREC_CHAR('n'): 658 /* higher risk disable it */ 659 return -1; 660 661 case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ 662 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 663 case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ 664 case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ 665 /* convert format char to lower , use Explicit conversion to clean up compilation warning */ 666 ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); 667 [[fallthrough]]; 668 case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ 669 case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ 670 case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ 671 case SECUREC_CHAR('a'): 672 { 673 /*if it's a private arg, just write <priate> to stream*/ 674 if (isPrivacy == 1) { 675#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 676 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 677 (void)va_arg(arglist, long double); 678 } else 679#endif 680 { 681 (void)va_arg(arglist, double); 682 } 683 break; 684 } 685 686 /* floating point conversion */ 687 formatBuf.str = buffer.str; /* output buffer for float string with default size */ 688 689 /* compute the precision value */ 690 if (formatAttr.precision < 0) { 691 formatAttr.precision = 6; 692 } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { 693 formatAttr.precision = 1; 694 } 695 696 /* calc buffer size to store long double value */ 697 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 698 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) { 699 noOutput = 1; 700 break; 701 } 702 bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision; 703 } else { 704 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) { 705 noOutput = 1; 706 break; 707 } 708 bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision; 709 } 710 if (formatAttr.fldWidth > bufferSize) { 711 bufferSize = formatAttr.fldWidth; 712 } 713 714 if (bufferSize >= SECUREC_BUFFER_SIZE) { 715 /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */ 716 /* size include '+' and '\0' */ 717 floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2)); 718 if (floatBuf != NULL) { 719 formatBuf.str = floatBuf; 720 } else { 721 noOutput = 1; 722 break; 723 } 724 } 725 726 { 727 /* add following code to call system sprintf API for float number */ 728 const SecChar *pFltFmt = format - 2; /* point to the position before 'f' or 'g' */ 729 int k; 730 int fltFmtStrLen; 731 char fltFmtBuf[SECUREC_FMT_STR_LEN]; 732 char *fltFmtStr = fltFmtBuf; 733 char *fltFmtHeap = NULL; /* to clear warning */ 734 735 /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/ 736 while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) { 737 --pFltFmt; 738 } 739 fltFmtStrLen = (int)((format - pFltFmt) + 1); /* with ending terminator */ 740 if (fltFmtStrLen > SECUREC_FMT_STR_LEN) { 741 /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ 742 fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen)); 743 if (fltFmtHeap == NULL) { 744 noOutput = 1; 745 break; 746 } else { 747 fltFmtHeap[0] = '%'; 748 for (k = 1; k < fltFmtStrLen - 1; ++k) { 749 /* convert wchar to char */ 750 fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */ 751 } 752 fltFmtHeap[k] = '\0'; 753 754 fltFmtStr = fltFmtHeap; 755 } 756 } else { 757 /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ 758 fltFmtBuf[0] = '%'; 759 for (k = 1; k < fltFmtStrLen - 1; ++k) { 760 /* convert wchar to char */ 761 fltFmtBuf[k] = (char)(pFltFmt[k]); /* copy the format string */ 762 } 763 fltFmtBuf[k] = '\0'; 764 } 765 766#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 767 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 768 long double tmp = (long double)va_arg(arglist, long double); 769 /* call system sprintf to format float value */ 770 if (formatAttr.dynWidth && formatAttr.dynPrecision) { 771 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 772 formatAttr.fldWidth,formatAttr.precision, tmp); 773 } else if (formatAttr.dynWidth) { 774 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 775 formatAttr.fldWidth, tmp); 776 } else if (formatAttr.dynPrecision) { 777 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 778 formatAttr.precision, tmp); 779 } else { 780 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); 781 } 782 } else 783#endif 784 { 785 double tmp = (double)va_arg(arglist, double); 786 if (formatAttr.dynWidth && formatAttr.dynPrecision) { 787 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, 788 formatAttr.precision, tmp); 789 } else if (formatAttr.dynWidth) { 790 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, 791 tmp); 792 } else if (formatAttr.dynPrecision) { 793 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision, 794 tmp); 795 } else { 796 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); 797 } 798 } 799 800 if (fltFmtHeap != NULL) { 801 /* if buffer is allocated on heap, free it */ 802 SECUREC_FREE(fltFmtHeap); 803 fltFmtHeap = NULL; 804 /* to clear e438 last value assigned not used , the compiler will optimize this code */ 805 (void)fltFmtHeap; 806 } 807 if (textLen < 0) { 808 /* bufferSize is large enough,just validation the return value */ 809 noOutput = 1; 810 break; 811 } 812 813 formatAttr.fldWidth = textLen; /* no padding ,this variable to calculate amount of padding */ 814 prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ 815 formatAttr.flags = 0; /* clear all internal formatAttr.flags */ 816 break; 817 } 818 } 819 820 case SECUREC_CHAR('p'): 821 /* print a pointer */ 822#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 823 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 824#else 825 formatAttr.flags |= SECUREC_FLAG_POINTER; 826#endif 827 828#ifdef SECUREC_ON_64BITS 829 formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ 830#else 831 formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ 832#endif 833 834#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) 835 836#if defined(SECUREC_VXWORKS_PLATFORM) 837 formatAttr.precision = 1; 838#else 839 formatAttr.precision = 0; 840#endif 841 formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ 842 digits = itoaLowerDigits; 843 goto OUTPUT_HEX; 844#else 845/* not linux vxwoks */ 846#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 847 formatAttr.precision = 1; 848#else 849 formatAttr.precision = 2 * sizeof(void *); 850#endif 851 852#endif 853 854#if defined(SECUREC_ON_UNIX) 855 digits = itoaLowerDigits; 856 goto OUTPUT_HEX; 857#endif 858 859 [[fallthrough]]; 860 case SECUREC_CHAR('X'): 861 /* unsigned upper hex output */ 862 digits = itoaUpperDigits; 863 goto OUTPUT_HEX; 864 case SECUREC_CHAR('x'): 865 /* unsigned lower hex output */ 866 digits = itoaLowerDigits; 867 868OUTPUT_HEX: 869 radix = 16; 870 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 871 /* alternate form means '0x' prefix */ 872 prefix[0] = SECUREC_CHAR('0'); 873 prefix[1] = (SecChar) (digits[16]); /* 'x' or 'X' */ 874 875#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) 876 if (ch == 'p') { 877 prefix[1] = SECUREC_CHAR('x'); 878 } 879#endif 880#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 881 if (ch == 'p') { 882 prefixLen = 0; 883 } else { 884 prefixLen = 2; 885 } 886#else 887 prefixLen = 2; 888#endif 889 890 } 891 goto OUTPUT_INT; 892 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 893 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 894 /* signed decimal output */ 895 formatAttr.flags |= SECUREC_FLAG_SIGNED; 896 [[fallthrough]]; 897 case SECUREC_CHAR('u'): 898 radix = 10; 899 goto OUTPUT_INT; 900 case SECUREC_CHAR('o'): 901 /* unsigned octal output */ 902 radix = 8; 903 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 904 /* alternate form means force a leading 0 */ 905 formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; 906 } 907OUTPUT_INT: 908 { 909 910 SecUnsignedInt64 number = 0; /* number to convert */ 911 SecInt64 l; /* temp long value */ 912 unsigned char tch; 913#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) 914 SecUnsignedInt32 digit = 0; /* ascii value of digit */ 915 SecUnsignedInt32 quotientHigh = 0; 916 SecUnsignedInt32 quotientLow = 0; 917#endif 918 919 /* read argument into variable l */ 920 if (formatAttr.flags & SECUREC_FLAG_I64) { 921 l = (SecInt64)va_arg(arglist, SecInt64); 922 } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { 923 l = (SecInt64)va_arg(arglist, SecInt64); 924 } else 925#ifdef SECUREC_ON_64BITS 926 if (formatAttr.flags & SECUREC_FLAG_LONG) { 927 l = (long)va_arg(arglist, long); 928 } else 929#endif /* SECUREC_ON_64BITS */ 930 if (formatAttr.flags & SECUREC_FLAG_CHAR) { 931 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 932 l = (char)va_arg(arglist, int); /* sign extend */ 933 if (l >= 128) { /* on some platform, char is always unsigned */ 934 SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; 935 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 936 tch = (unsigned char)(~(tmpL)); 937 l = tch + 1; 938 } 939 } else { 940 l = (unsigned char)va_arg(arglist, int); /* zero-extend */ 941 } 942 943 } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { 944 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 945 l = (short)va_arg(arglist, int); /* sign extend */ 946 } else { 947 l = (unsigned short)va_arg(arglist, int); /* zero-extend */ 948 } 949 950 } 951#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 952 else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { 953 l = (ptrdiff_t)va_arg(arglist, ptrdiff_t); /* sign extend */ 954 } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { 955 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 956 /* No suitable macros were found to handle the branch */ 957 if (SecIsSameSize(sizeof(size_t), sizeof(long))) { 958 l = va_arg(arglist, long); /* sign extend */ 959 } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { 960 l = va_arg(arglist, long long); /* sign extend */ 961 } else { 962 l = va_arg(arglist, int); /* sign extend */ 963 } 964 } else { 965 l = (SecInt64)(size_t)va_arg(arglist, size_t); /* sign extend */ 966 } 967 } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { 968 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 969 l = va_arg(arglist, SecInt64); /* sign extend */ 970 } else { 971 l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64); /* sign extend */ 972 } 973 } 974#endif 975 else { 976 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 977 l = va_arg(arglist, int); /* sign extend */ 978 } else { 979 l = (unsigned int)va_arg(arglist, int); /* zero-extend */ 980 } 981 982 } 983 /*if it's a private arg, just write <priate> to stream*/ 984 if (isPrivacy == 1) { 985 break; 986 } 987 988 /* check for negative; copy into number */ 989 if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { 990 number = (SecUnsignedInt64)(-l); 991 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 992 } else { 993 number = (SecUnsignedInt64)l; 994 } 995 996 if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && 997#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 998 ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && 999#endif 1000#ifdef SECUREC_ON_64BITS 1001 ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && 1002 ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && 1003#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ 1004 ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && 1005#endif 1006#endif 1007 ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { 1008 1009 number &= 0xffffffff; 1010 } 1011 1012 /* check precision value for default */ 1013 if (formatAttr.precision < 0) { 1014 formatAttr.precision = 1; /* default precision */ 1015 } else { 1016#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1017 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1018#else 1019 if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { 1020 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1021 } 1022#endif 1023 if (formatAttr.precision > SECUREC_MAX_PRECISION) { 1024 formatAttr.precision = SECUREC_MAX_PRECISION; 1025 } 1026 } 1027 1028 /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */ 1029 if (number == 0) { 1030#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux)) 1031 prefixLen = 0; 1032#else 1033 if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) 1034 prefixLen = 2; 1035 else 1036 prefixLen = 0; 1037#endif 1038 } 1039 1040 /* Convert data to ASCII */ 1041 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; 1042 1043 if (number > 0) { 1044#ifdef SECUREC_ON_64BITS 1045 switch (radix) { 1046 /* the compiler will optimize each one */ 1047 SECUREC_SPECIAL(number, 10); 1048 break; 1049 SECUREC_SPECIAL(number, 16); 1050 break; 1051 SECUREC_SPECIAL(number, 8); 1052 break; 1053 default: 1054 break; 1055 } 1056#else /* for 32 bits system */ 1057 if (number <= 0xFFFFFFFFUL) { 1058 /* in most case, the value to be converted is small value */ 1059 SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; 1060 switch (radix) { 1061 SECUREC_SPECIAL(n32Tmp, 16); 1062 break; 1063 SECUREC_SPECIAL(n32Tmp, 8); 1064 break; 1065 1066#ifdef _AIX 1067 /* the compiler will optimize div 10 */ 1068 SECUREC_SPECIAL(n32Tmp, 10); 1069 break; 1070#else 1071 case 10: 1072 { 1073 /* fast div 10 */ 1074 SecUnsignedInt32 q; 1075 SecUnsignedInt32 r; 1076 do { 1077 *--formatBuf.str = digits[n32Tmp % 10]; 1078 q = (n32Tmp >> 1) + (n32Tmp >> 2); 1079 q = q + (q >> 4); 1080 q = q + (q >> 8); 1081 q = q + (q >> 16); 1082 q = q >> 3; 1083 r = n32Tmp - (((q << 2) + q) << 1); 1084 n32Tmp = (r > 9) ? (q + 1) : q; 1085 } while (n32Tmp != 0); 1086 } 1087 break; 1088#endif 1089 default: 1090 break; 1091 } /* end switch */ 1092 } else { 1093 /* the value to be converted is greater than 4G */ 1094#if defined(SECUREC_VXWORKS_VERSION_5_4) 1095 do { 1096 if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16), 1097 (SecUnsignedInt32)number, 1098 (SecUnsignedInt32)radix, "ientHigh, "ientLow, &digit)) { 1099 noOutput = 1; 1100 break; 1101 } 1102 *--formatBuf.str = digits[digit]; 1103 1104 number = (SecUnsignedInt64)quotientHigh; 1105 number = (number << 32) + quotientLow; 1106 } while (number != 0); 1107#else 1108 switch (radix) { 1109 /* the compiler will optimize div 10 */ 1110 SECUREC_SPECIAL(number, 10); 1111 break; 1112 SECUREC_SPECIAL(number, 16); 1113 break; 1114 SECUREC_SPECIAL(number, 8); 1115 break; 1116 default: 1117 break; 1118 } 1119#endif 1120 } 1121#endif 1122 } /* END if (number > 0) */ 1123 /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */ 1124 textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str); 1125 if (formatAttr.precision > textLen) { 1126 for (ii = 0; ii < formatAttr.precision - textLen; ++ii) { 1127 *--formatBuf.str = '0'; 1128 } 1129 textLen = formatAttr.precision; 1130 } 1131 1132 /* Force a leading zero if FORCEOCTAL flag set */ 1133 if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) { 1134 *--formatBuf.str = '0'; 1135 ++textLen; /* add a zero */ 1136 } 1137 } 1138 break; 1139 default: 1140 break; 1141 } 1142 /*if it's a private arg, just write <priate> to stream*/ 1143 if (isPrivacy == 1) { 1144 SecWritePrivateStr(stream, &charsOut); 1145 break; 1146 } 1147 1148 if (noOutput == 0) { 1149 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1150 if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) { 1151 /* prefix is a '-' */ 1152 prefix[0] = SECUREC_CHAR('-'); 1153 prefixLen = 1; 1154 } else if (formatAttr.flags & SECUREC_FLAG_SIGN) { 1155 /* prefix is '+' */ 1156 prefix[0] = SECUREC_CHAR('+'); 1157 prefixLen = 1; 1158 } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) { 1159 /* prefix is ' ' */ 1160 prefix[0] = SECUREC_CHAR(' '); 1161 prefixLen = 1; 1162 } 1163 } 1164 1165#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) 1166 if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) { 1167 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1168 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1]; 1169 *formatBuf.str-- = '\0'; 1170 *formatBuf.str-- = ')'; 1171 *formatBuf.str-- = 'l'; 1172 *formatBuf.str-- = 'i'; 1173 *formatBuf.str-- = 'n'; 1174 *formatBuf.str = '('; 1175 textLen = 5; 1176 } 1177#endif 1178 1179 /* calculate amount of padding */ 1180 padding = (formatAttr.fldWidth - textLen) - prefixLen; 1181 1182 /* put out the padding, prefix, and text, in the correct order */ 1183 1184 if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) { 1185 /* pad on left with blanks */ 1186 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { 1187 /* char * cast to wchar * */ 1188 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); 1189 } else { 1190 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); 1191 } 1192 } 1193 1194 /* write prefix */ 1195 if (prefixLen > 0) { 1196 SecChar *pPrefix = prefix; 1197 if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) { 1198 /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */ 1199 SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut); 1200 } else { 1201 SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut); 1202 } 1203 } 1204 1205 if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) 1206 && padding > 0) { 1207 /* write leading zeros */ 1208 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { 1209 /* char * cast to wchar * */ 1210 SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut); 1211 } else { 1212 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut); 1213 } 1214 } 1215 1216 /* write text */ 1217#ifndef SECUREC_FOR_WCHAR 1218 if (formatAttr.bufferIsWide && (textLen > 0)) { 1219 wchar_t *p = formatBuf.wStr; 1220 int count = textLen; 1221 while (count--) { 1222 char tmpBuf[SECUREC_MB_LEN + 1]; 1223 SECUREC_MASK_MSVC_CRT_WARNING 1224 int retVal = wctomb(tmpBuf, *p++); 1225 SECUREC_END_MASK_MSVC_CRT_WARNING 1226 if (retVal <= 0) { 1227 charsOut = -1; 1228 break; 1229 } 1230 SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut); 1231 } 1232 } else { 1233 if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) { 1234 SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut); 1235 } else { 1236 SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut); 1237 } 1238 } 1239#else /* SECUREC_FOR_WCHAR */ 1240 if (formatAttr.bufferIsWide == 0 && textLen > 0) { 1241 int count = textLen; 1242 char *p = formatBuf.str; 1243 1244 while (count > 0) { 1245 wchar_t wchar = L'\0'; 1246 int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX); 1247 if (retVal <= 0) { 1248 charsOut = -1; 1249 break; 1250 } 1251 SECUREC_WRITE_CHAR(wchar, stream, &charsOut); 1252 p += retVal; 1253 count -= retVal; 1254 } 1255 } else { 1256 if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) { 1257 SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */ 1258 } else { 1259 SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut); 1260 } 1261 } 1262#endif /* SECUREC_FOR_WCHAR */ 1263 1264 if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { 1265 /* pad on right with blanks */ 1266 if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { 1267 /* char * cast to wchar * */ 1268 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); 1269 } else { 1270 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); 1271 } 1272 } 1273 1274 /* we're done! */ 1275 } 1276 if (floatBuf != NULL) { 1277 SECUREC_FREE(floatBuf); 1278 floatBuf = NULL; 1279 } 1280 break; 1281 case STAT_INVALID: 1282 return -1; 1283 default: 1284 return -1; /* input format is wrong, directly return */ 1285 } 1286 } 1287 1288 if (state != STAT_NORMAL && state != STAT_TYPE) { 1289 return -1; 1290 } 1291 1292 return charsOut; /* the number of characters written */ 1293} /* arglist must not be declare as const */ 1294#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */ 1295 1296