Skip to content

Parsing invalid strings #148

Description

@rlalik

I have a code like this:

template<typename... T1, template<typename...> class U, typename... T2, template<typename...> class V>
struct tuple_pair_scanner<U<T1...>, V<T2...>>
{
    auto operator()(auto input, std::string_view fmt_addr, std::string_view fmt_row)
        -> std::pair<std::tuple<T1...>, std::tuple<T2...>>
    {
        auto res_addr = scn::scan<T1...>(input, scn::runtime_format(fmt_addr));
        auto res_row = scn::scan<T2...>(res_addr->range(), scn::runtime_format(fmt_row));

        // this is for debugging #1
        fmt::print("{} {} {} {}, {}\n",
                   res_addr->values(),
                   res_row->values(),
                   sizeof(res_addr->values()) == sizeof(std::tuple<T1...>),
                   sizeof(res_row->values()) == sizeof(std::tuple<T2...>),
                   res_row->end() - res_row->begin());

        // this is for debugging #2
        fmt::print("{} {} {} {}, {} {}\n",
                   res_addr->values(),
                   res_row->values(),
                   sizeof(res_addr->values()) == sizeof(std::tuple<T1...>),
                   sizeof(res_row->values()) == sizeof(std::tuple<T2...>),
                   res_row->range(), res_row->end() - res_row->begin());

        return {res_addr->values(), res_row->values()};
    }
};

which I call:

tuple_pair_scanner<std::tuple<int, int>, std::tuple<int, int>> scanner;
scanner(line, "{:x} {}", "{} {}")

and scan line by line input (the third line is invalid on purpose):

0x1000 0    0 0
0x1000 1    0 1
0x1000 2    3
0x1001 0    1 0

When using debugging no. 1, I have output:

(4096, 0) (0, 0) true true , 0
(4096, 1) (0, 1) true true , 0
(4096, 2) (3, 0) true true , -139745094807973
(4097, 0) (1, 0) true true , 0

while when trying to use debugging no. 2:

(4096, 0) (0, 0) true true , [] 0
(4096, 1) (0, 1) true true , [] 0

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007fdea9dd3417 in ?? () from /usr/lib64/libc.so.6
#1  0x00007fdea9dd3441 in ?? () from /usr/lib64/libc.so.6
#2  0x00007fdea9e4252b in wait4 () from /usr/lib64/libc.so.6
#3  0x00007fdea9d93dfb in ?? () from /usr/lib64/libc.so.6
#4  0x00007fdeaab459e2 in TUnixSystem::StackTrace() () from /usr/lib64/root/libCore.so.6.36
#5  0x00007fdeaab45328 in TUnixSystem::DispatchSignals(ESignals) () from /usr/lib64/root/libCore.so.6.36
#6  <signal handler called>
#7  0x0000559965525ad5 in void fmt::v11::detail::value<fmt::v11::context>::format_custom<scn::v4::ranges::detail::subrange_::subrange<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, fmt::v11::formatter<scn::v4::ranges::detail::subrange_::subrange<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, char, void> >(void*, fmt::v11::parse_context<char>&, fmt::v11::context&) ()
#8  0x00007fdeaa59fbbd in ?? () from /usr/lib64/libfmt.so.11
#9  0x00007fdeaa5a1f4a in ?? () from /usr/lib64/libfmt.so.11
#10 0x00007fdeaa591a0d in fmt::v11::detail::vformat_to(fmt::v11::detail::buffer<char>&, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>, fmt::v11::detail::locale_ref) () from /usr/lib64/libfmt.so.11
#11 0x00007fdeaa591ff3 in fmt::v11::vprint_buffered(_IO_FILE*, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>) () from /usr/lib64/libfmt.so.11
... rest o the trace stack

My questions are:

  1. What is the proper way to detect that the input does not contain enough input values? scan_result does not provide any function which returns number of scan elements, and the returned tuple size is equal to the templated function call. The returned value is 0 but it can be a valid value.
  2. Why result->range() creashes? is it a bug or feature (by design?). What should it return if it was correct?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions