1 //===-- Unittests for the printf Parser -----------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/__support/CPP/bit.h" 10 #include "src/__support/CPP/string_view.h" 11 #include "src/__support/arg_list.h" 12 #include "src/stdio/printf_core/parser.h" 13 14 #include <stdarg.h> 15 16 #include "test/UnitTest/PrintfMatcher.h" 17 #include "test/UnitTest/Test.h" 18 19 using LIBC_NAMESPACE::cpp::string_view; 20 using LIBC_NAMESPACE::internal::ArgList; 21 22 void init(const char *__restrict str, ...) { 23 va_list vlist; 24 va_start(vlist, str); 25 ArgList v(vlist); 26 va_end(vlist); 27 28 LIBC_NAMESPACE::printf_core::Parser<ArgList> parser(str, v); 29 } 30 31 void evaluate(LIBC_NAMESPACE::printf_core::FormatSection *format_arr, 32 const char *__restrict str, ...) { 33 va_list vlist; 34 va_start(vlist, str); 35 ArgList v(vlist); 36 va_end(vlist); 37 38 LIBC_NAMESPACE::printf_core::Parser<ArgList> parser(str, v); 39 40 for (auto cur_section = parser.get_next_section(); 41 !cur_section.raw_string.empty(); 42 cur_section = parser.get_next_section()) { 43 *format_arr = cur_section; 44 ++format_arr; 45 } 46 } 47 48 TEST(LlvmLibcPrintfParserTest, Constructor) { init("test", 1, 2); } 49 50 TEST(LlvmLibcPrintfParserTest, EvalRaw) { 51 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 52 const char *str = "test"; 53 evaluate(format_arr, str); 54 55 LIBC_NAMESPACE::printf_core::FormatSection expected; 56 expected.has_conv = false; 57 58 expected.raw_string = {str, 4}; 59 60 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 61 // TODO: add checks that the format_arr after the last one has length 0 62 } 63 64 TEST(LlvmLibcPrintfParserTest, EvalSimple) { 65 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 66 const char *str = "test %% test"; 67 evaluate(format_arr, str); 68 69 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2; 70 expected0.has_conv = false; 71 72 expected0.raw_string = {str, 5}; 73 74 ASSERT_PFORMAT_EQ(expected0, format_arr[0]); 75 76 expected1.has_conv = true; 77 78 expected1.raw_string = {str + 5, 2}; 79 expected1.conv_name = '%'; 80 81 ASSERT_PFORMAT_EQ(expected1, format_arr[1]); 82 83 expected2.has_conv = false; 84 85 expected2.raw_string = {str + 7, 5}; 86 87 ASSERT_PFORMAT_EQ(expected2, format_arr[2]); 88 } 89 90 TEST(LlvmLibcPrintfParserTest, EvalOneArg) { 91 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 92 const char *str = "%d"; 93 int arg1 = 12345; 94 evaluate(format_arr, str, arg1); 95 96 LIBC_NAMESPACE::printf_core::FormatSection expected; 97 expected.has_conv = true; 98 99 expected.raw_string = {str, 2}; 100 expected.conv_val_raw = arg1; 101 expected.conv_name = 'd'; 102 103 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 104 } 105 106 TEST(LlvmLibcPrintfParserTest, EvalBadArg) { 107 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 108 const char *str = "%\0abc"; 109 int arg1 = 12345; 110 evaluate(format_arr, str, arg1); 111 112 LIBC_NAMESPACE::printf_core::FormatSection expected; 113 expected.has_conv = false; 114 expected.raw_string = {str, 1}; 115 116 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 117 } 118 119 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFlags) { 120 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 121 const char *str = "%+-0 #d"; 122 int arg1 = 12345; 123 evaluate(format_arr, str, arg1); 124 125 LIBC_NAMESPACE::printf_core::FormatSection expected; 126 expected.has_conv = true; 127 128 expected.raw_string = {str, 7}; 129 expected.flags = static_cast<LIBC_NAMESPACE::printf_core::FormatFlags>( 130 LIBC_NAMESPACE::printf_core::FormatFlags::FORCE_SIGN | 131 LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED | 132 LIBC_NAMESPACE::printf_core::FormatFlags::LEADING_ZEROES | 133 LIBC_NAMESPACE::printf_core::FormatFlags::SPACE_PREFIX | 134 LIBC_NAMESPACE::printf_core::FormatFlags::ALTERNATE_FORM); 135 expected.conv_val_raw = arg1; 136 expected.conv_name = 'd'; 137 138 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 139 } 140 141 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithWidth) { 142 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 143 const char *str = "%12d"; 144 int arg1 = 12345; 145 evaluate(format_arr, str, arg1); 146 147 LIBC_NAMESPACE::printf_core::FormatSection expected; 148 expected.has_conv = true; 149 150 expected.raw_string = {str, 4}; 151 expected.min_width = 12; 152 expected.conv_val_raw = arg1; 153 expected.conv_name = 'd'; 154 155 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 156 } 157 158 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithPrecision) { 159 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 160 const char *str = "%.34d"; 161 int arg1 = 12345; 162 evaluate(format_arr, str, arg1); 163 164 LIBC_NAMESPACE::printf_core::FormatSection expected; 165 expected.has_conv = true; 166 167 expected.raw_string = {str, 5}; 168 expected.precision = 34; 169 expected.conv_val_raw = arg1; 170 expected.conv_name = 'd'; 171 172 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 173 } 174 175 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithTrivialPrecision) { 176 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 177 const char *str = "%.d"; 178 int arg1 = 12345; 179 evaluate(format_arr, str, arg1); 180 181 LIBC_NAMESPACE::printf_core::FormatSection expected; 182 expected.has_conv = true; 183 184 expected.raw_string = {str, 3}; 185 expected.precision = 0; 186 expected.conv_val_raw = arg1; 187 expected.conv_name = 'd'; 188 189 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 190 } 191 192 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithShortLengthModifier) { 193 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 194 const char *str = "%hd"; 195 int arg1 = 12345; 196 evaluate(format_arr, str, arg1); 197 198 LIBC_NAMESPACE::printf_core::FormatSection expected; 199 expected.has_conv = true; 200 201 expected.raw_string = {str, 3}; 202 expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::h; 203 expected.conv_val_raw = arg1; 204 expected.conv_name = 'd'; 205 206 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 207 } 208 209 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) { 210 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 211 const char *str = "%lld"; 212 long long arg1 = 12345; 213 evaluate(format_arr, str, arg1); 214 215 LIBC_NAMESPACE::printf_core::FormatSection expected; 216 expected.has_conv = true; 217 218 expected.raw_string = {str, 4}; 219 expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::ll; 220 expected.conv_val_raw = arg1; 221 expected.conv_name = 'd'; 222 223 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 224 } 225 226 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithBitWidthLengthModifier) { 227 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 228 const char *str = "%w32d"; 229 long long arg1 = 12345; 230 evaluate(format_arr, str, arg1); 231 232 LIBC_NAMESPACE::printf_core::FormatSection expected; 233 expected.has_conv = true; 234 235 expected.raw_string = {str, 5}; 236 expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::w; 237 expected.bit_width = 32; 238 expected.conv_val_raw = arg1; 239 expected.conv_name = 'd'; 240 241 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 242 } 243 244 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFastBitWidthLengthModifier) { 245 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 246 const char *str = "%wf32d"; 247 long long arg1 = 12345; 248 evaluate(format_arr, str, arg1); 249 250 LIBC_NAMESPACE::printf_core::FormatSection expected; 251 expected.has_conv = true; 252 253 expected.raw_string = {str, 6}; 254 expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::wf; 255 expected.bit_width = 32; 256 expected.conv_val_raw = arg1; 257 expected.conv_name = 'd'; 258 259 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 260 } 261 262 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) { 263 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 264 const char *str = "% -056.78jd"; 265 intmax_t arg1 = 12345; 266 evaluate(format_arr, str, arg1); 267 268 LIBC_NAMESPACE::printf_core::FormatSection expected; 269 expected.has_conv = true; 270 271 expected.raw_string = {str, 11}; 272 expected.flags = static_cast<LIBC_NAMESPACE::printf_core::FormatFlags>( 273 LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED | 274 LIBC_NAMESPACE::printf_core::FormatFlags::LEADING_ZEROES | 275 LIBC_NAMESPACE::printf_core::FormatFlags::SPACE_PREFIX); 276 expected.min_width = 56; 277 expected.precision = 78; 278 expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::j; 279 expected.conv_val_raw = arg1; 280 expected.conv_name = 'd'; 281 282 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 283 } 284 285 TEST(LlvmLibcPrintfParserTest, EvalThreeArgs) { 286 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 287 const char *str = "%d%f%s"; 288 int arg1 = 12345; 289 double arg2 = 123.45; 290 const char *arg3 = "12345"; 291 evaluate(format_arr, str, arg1, arg2, arg3); 292 293 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2; 294 expected0.has_conv = true; 295 296 expected0.raw_string = {str, 2}; 297 expected0.conv_val_raw = arg1; 298 expected0.conv_name = 'd'; 299 300 ASSERT_PFORMAT_EQ(expected0, format_arr[0]); 301 302 expected1.has_conv = true; 303 304 expected1.raw_string = {str + 2, 2}; 305 expected1.conv_val_raw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(arg2); 306 expected1.conv_name = 'f'; 307 308 ASSERT_PFORMAT_EQ(expected1, format_arr[1]); 309 310 expected2.has_conv = true; 311 312 expected2.raw_string = {str + 4, 2}; 313 expected2.conv_val_ptr = const_cast<char *>(arg3); 314 expected2.conv_name = 's'; 315 316 ASSERT_PFORMAT_EQ(expected2, format_arr[2]); 317 } 318 319 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithOverflowingWidthAndPrecision) { 320 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 321 const char *str = "%-999999999999.999999999999d"; 322 int arg1 = 12345; 323 evaluate(format_arr, str, arg1); 324 325 LIBC_NAMESPACE::printf_core::FormatSection expected; 326 expected.has_conv = true; 327 328 expected.raw_string = {str, 28}; 329 expected.flags = LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED; 330 expected.min_width = INT_MAX; 331 expected.precision = INT_MAX; 332 expected.conv_val_raw = arg1; 333 expected.conv_name = 'd'; 334 335 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 336 } 337 338 TEST(LlvmLibcPrintfParserTest, 339 EvalOneArgWithOverflowingWidthAndPrecisionAsArgs) { 340 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 341 const char *str = "%*.*d"; 342 int arg1 = INT_MIN; // INT_MIN = -2147483648 if int is 32 bits. 343 int arg2 = INT_MIN; 344 int arg3 = 12345; 345 evaluate(format_arr, str, arg1, arg2, arg3); 346 347 LIBC_NAMESPACE::printf_core::FormatSection expected; 348 expected.has_conv = true; 349 350 expected.raw_string = {str, 5}; 351 expected.flags = LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED; 352 expected.min_width = INT_MAX; 353 expected.precision = arg2; 354 expected.conv_val_raw = arg3; 355 expected.conv_name = 'd'; 356 357 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 358 } 359 360 #ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE 361 362 TEST(LlvmLibcPrintfParserTest, IndexModeOneArg) { 363 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 364 const char *str = "%1$d"; 365 int arg1 = 12345; 366 evaluate(format_arr, str, arg1); 367 368 LIBC_NAMESPACE::printf_core::FormatSection expected; 369 expected.has_conv = true; 370 371 expected.raw_string = {str, 4}; 372 expected.conv_val_raw = arg1; 373 expected.conv_name = 'd'; 374 375 ASSERT_PFORMAT_EQ(expected, format_arr[0]); 376 } 377 378 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsSequential) { 379 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 380 const char *str = "%1$d%2$f%3$s"; 381 int arg1 = 12345; 382 double arg2 = 123.45; 383 const char *arg3 = "12345"; 384 evaluate(format_arr, str, arg1, arg2, arg3); 385 386 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2; 387 expected0.has_conv = true; 388 389 expected0.raw_string = {str, 4}; 390 expected0.conv_val_raw = arg1; 391 expected0.conv_name = 'd'; 392 393 ASSERT_PFORMAT_EQ(expected0, format_arr[0]); 394 395 expected1.has_conv = true; 396 397 expected1.raw_string = {str + 4, 4}; 398 expected1.conv_val_raw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(arg2); 399 expected1.conv_name = 'f'; 400 401 ASSERT_PFORMAT_EQ(expected1, format_arr[1]); 402 403 expected2.has_conv = true; 404 405 expected2.raw_string = {str + 8, 4}; 406 expected2.conv_val_ptr = const_cast<char *>(arg3); 407 expected2.conv_name = 's'; 408 409 ASSERT_PFORMAT_EQ(expected2, format_arr[2]); 410 } 411 412 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsReverse) { 413 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 414 const char *str = "%3$d%2$f%1$s"; 415 int arg1 = 12345; 416 double arg2 = 123.45; 417 const char *arg3 = "12345"; 418 evaluate(format_arr, str, arg3, arg2, arg1); 419 420 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2; 421 expected0.has_conv = true; 422 423 expected0.raw_string = {str, 4}; 424 expected0.conv_val_raw = arg1; 425 expected0.conv_name = 'd'; 426 427 ASSERT_PFORMAT_EQ(expected0, format_arr[0]); 428 429 expected1.has_conv = true; 430 431 expected1.raw_string = {str + 4, 4}; 432 expected1.conv_val_raw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(arg2); 433 expected1.conv_name = 'f'; 434 435 ASSERT_PFORMAT_EQ(expected1, format_arr[1]); 436 437 expected2.has_conv = true; 438 439 expected2.raw_string = {str + 8, 4}; 440 expected2.conv_val_ptr = const_cast<char *>(arg3); 441 expected2.conv_name = 's'; 442 443 ASSERT_PFORMAT_EQ(expected2, format_arr[2]); 444 } 445 446 TEST(LlvmLibcPrintfParserTest, IndexModeTenArgsRandom) { 447 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 448 const char *str = "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d"; 449 int args[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10}; 450 evaluate(format_arr, str, args[0], args[1], args[2], args[3], args[4], 451 args[5], args[6], args[7], args[8], args[9]); 452 453 for (size_t i = 0; i < 10; ++i) { 454 LIBC_NAMESPACE::printf_core::FormatSection expected; 455 expected.has_conv = true; 456 457 expected.raw_string = {str + (4 * i), 458 static_cast<size_t>(4 + (i >= 9 ? 1 : 0))}; 459 expected.conv_val_raw = i + 1; 460 expected.conv_name = 'd'; 461 EXPECT_PFORMAT_EQ(expected, format_arr[i]); 462 } 463 } 464 465 TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) { 466 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 467 const char *str = "normal text %3$llu %% %2$ *4$f %2$ .*4$f %1$1.1c"; 468 char arg1 = '1'; 469 double arg2 = 123.45; 470 unsigned long long arg3 = 12345; 471 int arg4 = 10; 472 evaluate(format_arr, str, arg1, arg2, arg3, arg4); 473 474 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2, 475 expected3, expected4, expected5, expected6, expected7, expected8, 476 expected9; 477 478 expected0.has_conv = false; 479 480 expected0.raw_string = {str, 12}; 481 482 EXPECT_PFORMAT_EQ(expected0, format_arr[0]); 483 484 expected1.has_conv = true; 485 486 expected1.raw_string = {str + 12, 6}; 487 expected1.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::ll; 488 expected1.conv_val_raw = arg3; 489 expected1.conv_name = 'u'; 490 491 EXPECT_PFORMAT_EQ(expected1, format_arr[1]); 492 493 expected2.has_conv = false; 494 495 expected2.raw_string = {str + 18, 1}; 496 497 EXPECT_PFORMAT_EQ(expected2, format_arr[2]); 498 499 expected3.has_conv = true; 500 501 expected3.raw_string = {str + 19, 2}; 502 expected3.conv_name = '%'; 503 504 EXPECT_PFORMAT_EQ(expected3, format_arr[3]); 505 506 expected4.has_conv = false; 507 508 expected4.raw_string = {str + 21, 1}; 509 510 EXPECT_PFORMAT_EQ(expected4, format_arr[4]); 511 512 expected5.has_conv = true; 513 514 expected5.raw_string = {str + 22, 8}; 515 expected5.flags = LIBC_NAMESPACE::printf_core::FormatFlags::SPACE_PREFIX; 516 expected5.min_width = arg4; 517 expected5.conv_val_raw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(arg2); 518 expected5.conv_name = 'f'; 519 520 EXPECT_PFORMAT_EQ(expected5, format_arr[5]); 521 522 expected6.has_conv = false; 523 524 expected6.raw_string = {str + 30, 1}; 525 526 EXPECT_PFORMAT_EQ(expected6, format_arr[6]); 527 528 expected7.has_conv = true; 529 530 expected7.raw_string = {str + 31, 9}; 531 expected7.flags = LIBC_NAMESPACE::printf_core::FormatFlags::SPACE_PREFIX; 532 expected7.precision = arg4; 533 expected7.conv_val_raw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(arg2); 534 expected7.conv_name = 'f'; 535 536 EXPECT_PFORMAT_EQ(expected7, format_arr[7]); 537 538 expected8.has_conv = false; 539 540 expected8.raw_string = {str + 40, 1}; 541 542 EXPECT_PFORMAT_EQ(expected8, format_arr[8]); 543 544 expected9.has_conv = true; 545 546 expected9.raw_string = {str + 41, 7}; 547 expected9.min_width = 1; 548 expected9.precision = 1; 549 expected9.conv_val_raw = arg1; 550 expected9.conv_name = 'c'; 551 552 EXPECT_PFORMAT_EQ(expected9, format_arr[9]); 553 } 554 555 TEST(LlvmLibcPrintfParserTest, IndexModeGapCheck) { 556 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 557 const char *str = "%1$d%2$d%4$d"; 558 int arg1 = 1; 559 int arg2 = 2; 560 int arg3 = 3; 561 int arg4 = 4; 562 563 evaluate(format_arr, str, arg1, arg2, arg3, arg4); 564 565 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1, expected2; 566 567 expected0.has_conv = true; 568 expected0.raw_string = {str, 4}; 569 expected0.conv_val_raw = arg1; 570 expected0.conv_name = 'd'; 571 572 EXPECT_PFORMAT_EQ(expected0, format_arr[0]); 573 574 expected1.has_conv = true; 575 expected1.raw_string = {str + 4, 4}; 576 expected1.conv_val_raw = arg2; 577 expected1.conv_name = 'd'; 578 579 EXPECT_PFORMAT_EQ(expected1, format_arr[1]); 580 581 expected2.has_conv = false; 582 expected2.raw_string = {str + 8, 4}; 583 584 EXPECT_PFORMAT_EQ(expected2, format_arr[2]); 585 } 586 587 TEST(LlvmLibcPrintfParserTest, IndexModeTrailingPercentCrash) { 588 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 589 const char *str = "%2$d%"; 590 evaluate(format_arr, str, 1, 2); 591 592 LIBC_NAMESPACE::printf_core::FormatSection expected0, expected1; 593 expected0.has_conv = false; 594 595 expected0.raw_string = {str, 4}; 596 EXPECT_PFORMAT_EQ(expected0, format_arr[0]); 597 598 expected1.has_conv = false; 599 600 expected1.raw_string = {str + 4, 1}; 601 EXPECT_PFORMAT_EQ(expected1, format_arr[1]); 602 } 603 604 TEST(LlvmLibcPrintfParserTest, DoublePercentIsAllowedInvalidIndex) { 605 LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; 606 607 // Normally this conversion specifier would be raw (due to having a width 608 // defined as an invalid argument) but since it's a % conversion it's allowed 609 // by this specific parser. Any % conversion that is not just "%%" is 610 // undefined, so this is implementation-specific behavior. 611 // The goal is to be consistent. A conversion specifier of "%L%" is also 612 // undefined, but is traditionally displayed as just "%". "%2%" is also 613 // displayed as "%", even though if the width was respected it should be " %". 614 // Finally, "%*%" traditionally is displayed as "%" but also traditionally 615 // consumes an argument, since the * consumes an integer. Therefore, having 616 // "%*2$%" display as "%" is consistent with other printf behavior. 617 const char *str = "%*2$%"; 618 619 evaluate(format_arr, str, 1, 2); 620 621 LIBC_NAMESPACE::printf_core::FormatSection expected0; 622 expected0.has_conv = true; 623 624 expected0.raw_string = str; 625 expected0.conv_name = '%'; 626 EXPECT_PFORMAT_EQ(expected0, format_arr[0]); 627 } 628 629 #endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE 630