Skip to content

Commit a986587

Browse files
philnik777kcloudy0717
authored andcommitted
[libc++] Fix num_get base parsing (llvm#170460)
This fixes two bugs reported in llvm#121795 and adds regression tests. Specifically, these bugs are in the base detection mechanism. The first bug is that the out parameter isn't set when the stream only contains zero and after that is the end of the stream. The second one is that we don't consider `0` to be a number, and instead we only parse it as the start of an octal literal.
1 parent 844de3c commit a986587

File tree

2 files changed

+98
-0
lines changed
  • libcxx
    • include/__locale_dir
    • test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members

2 files changed

+98
-0
lines changed

libcxx/include/__locale_dir/num.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
436436
++__first;
437437
if (__first == __last) {
438438
__err |= ios_base::eofbit;
439+
__v = 0;
439440
return __first;
440441
}
441442
// __c2 == 'x' || __c2 == 'X'
@@ -444,6 +445,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
444445
++__first;
445446
} else {
446447
__base = 8;
448+
__parsed_num = true; // We only swallowed '0', so we've started to parse a number
447449
}
448450
} else {
449451
__base = 10;

libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,5 +670,101 @@ int main(int, char**)
670670
assert(v == std::numeric_limits<long>::min());
671671
}
672672

673+
{ // Check that auto-detection of the base works properly
674+
ios.flags(ios.flags() & ~std::ios::basefield);
675+
{ // zeroes
676+
{
677+
v = -1;
678+
const char str[] = "0";
679+
std::ios_base::iostate err = ios.goodbit;
680+
681+
cpp17_input_iterator<const char*> iter =
682+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 1), ios, err, v);
683+
assert(base(iter) == str + 1);
684+
assert(err == ios.eofbit);
685+
assert(v == 0);
686+
}
687+
{
688+
v = -1;
689+
const char str[] = "00";
690+
std::ios_base::iostate err = ios.goodbit;
691+
692+
cpp17_input_iterator<const char*> iter =
693+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
694+
assert(base(iter) == str + 2);
695+
assert(err == ios.eofbit);
696+
assert(v == 0);
697+
}
698+
{
699+
v = -1;
700+
const char str[] = "0x0";
701+
std::ios_base::iostate err = ios.goodbit;
702+
703+
cpp17_input_iterator<const char*> iter =
704+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
705+
assert(base(iter) == str + 3);
706+
assert(err == ios.eofbit);
707+
assert(v == 0);
708+
}
709+
{
710+
v = -1;
711+
const char str[] = "0X0";
712+
std::ios_base::iostate err = ios.goodbit;
713+
714+
cpp17_input_iterator<const char*> iter =
715+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
716+
assert(base(iter) == str + 3);
717+
assert(err == ios.eofbit);
718+
assert(v == 0);
719+
}
720+
}
721+
{ // first character after base is out of range
722+
{
723+
v = -1;
724+
const char str[] = "08";
725+
std::ios_base::iostate err = ios.goodbit;
726+
727+
cpp17_input_iterator<const char*> iter =
728+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
729+
assert(base(iter) == str + 1);
730+
assert(err == ios.goodbit);
731+
assert(v == 0);
732+
}
733+
{
734+
v = -1;
735+
const char str[] = "1a";
736+
std::ios_base::iostate err = ios.goodbit;
737+
738+
cpp17_input_iterator<const char*> iter =
739+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
740+
assert(base(iter) == str + 1);
741+
assert(err == ios.goodbit);
742+
assert(v == 1);
743+
}
744+
{
745+
v = -1;
746+
const char str[] = "0xg";
747+
std::ios_base::iostate err = ios.goodbit;
748+
749+
cpp17_input_iterator<const char*> iter =
750+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
751+
assert(base(iter) == str + 2);
752+
assert(err == ios.failbit);
753+
assert(v == 0);
754+
}
755+
{
756+
v = -1;
757+
const char str[] = "0Xg";
758+
std::ios_base::iostate err = ios.goodbit;
759+
760+
cpp17_input_iterator<const char*> iter =
761+
f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
762+
assert(base(iter) == str + 2);
763+
assert(err == ios.failbit);
764+
assert(v == 0);
765+
}
766+
}
767+
}
768+
673769
return 0;
674770
}

0 commit comments

Comments
 (0)