Skip to content

Commit

Permalink
Fix bug with double-wide characters triggering invalid field width ca…
Browse files Browse the repository at this point in the history
…lculation
  • Loading branch information
eliaskosunen committed Nov 6, 2024
1 parent e35d46f commit d815877
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/scn/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2521,6 +2521,13 @@ class counted_width_iterator {
return m_multibyte_left;
}

bool is_current_double_wide() const
{
assert(count() != 0 || multibyte_left() != 0);
return _get_width_at_current_cp_start(
_get_cp_length_at_current()) == 2;
}

constexpr decltype(auto) operator*()
{
return *m_current;
Expand Down Expand Up @@ -2634,12 +2641,14 @@ class counted_width_iterator {
friend constexpr bool operator==(const counted_width_iterator& x,
ranges::default_sentinel_t)
{
return x.count() == 0 && x.multibyte_left() == 0;
return (x.count() == 0 && x.multibyte_left() == 0) ||
(x.count() == 1 && x.multibyte_left() == 0 &&
x.is_current_double_wide());
}
friend constexpr bool operator==(ranges::default_sentinel_t,
friend constexpr bool operator==(ranges::default_sentinel_t s,
const counted_width_iterator& x)
{
return x.count() == 0 && x.multibyte_left() == 0;
return x == s;
}

friend constexpr bool operator!=(const counted_width_iterator& a,
Expand Down Expand Up @@ -2868,7 +2877,9 @@ class take_width_view : public ranges::view_interface<take_width_view<View>> {
friend constexpr bool operator==(const CWI& y, const sentinel& x)
{
return (y.count() == 0 && y.multibyte_left() == 0) ||
y.base() == x.m_end;
y.base() == x.m_end ||
(y.count() == 1 && y.multibyte_left() == 0 &&
y.is_current_double_wide());
}

friend constexpr bool operator==(const sentinel& x, const CWI& y)
Expand Down
8 changes: 8 additions & 0 deletions tests/unittests/align_and_fill_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,3 +629,11 @@ TEST(CustomPrecisionTest, DoubleWidthEmoji)
EXPECT_EQ(r->value(), "😂");
EXPECT_STREQ(r->begin(), "a");
}

TEST(CustomPrecisionTest, Fuzz1)
{
auto r = scn::scan<std::string>("a😂", "{:^.2}");
ASSERT_TRUE(r);
EXPECT_EQ(r->value(), "a");
EXPECT_STREQ(r->begin(), "😂");
}

0 comments on commit d815877

Please sign in to comment.