boostorg / locale

Boost.Locale
Boost Software License 1.0
31 stars 70 forks source link

Use of boost::locale::collator crashes when not using ICU/WinAPI #215

Closed Flamefire closed 7 months ago

Flamefire commented 7 months ago

However, when I try to use it, this snippet crashes the application:

// Initialize boost::locale
    boost::locale::generator gen;
    std::locale loc = gen("");
    const boost::locale::collator<char>& coll = std::use_facet<boost::locale::collator<char>>(loc);

    auto result = coll.compare(boost::locale::collate_level::secondary, str1, str2);
    if (result < 0) return -1;
    if (result > 0) return 1;
    return 0;

In the file: collator.hpp - see the screenshots from Xcode debugger. Skjermbilde 2024-01-04 kl  10 56 40 Skjermbilde 2024-01-04 kl  10 57 32 Skjermbilde 2024-01-04 kl  10 57 20 Skjermbilde 2024-01-04 kl  10 57 01

Originally posted by @olekrisek in https://github.com/boostorg/locale/issues/210#issuecomment-1876819426

Flamefire commented 7 months ago

It looks like the virtual function dispatch gets messed up in your use case as indicated by __cxxabiv1::__si_class_type_info in the call stack which doesn't look right.

The actual type of boost::locale::collator<char>, i.e. of *this inside the compare call is likely one from boost::locale::impl_std or boost::locale::impl_posix. And those only derive from std::collate but not from boost::locale::collate which means they do not implement that do_compare function taking a level argument. And seemingly std::use_facet does not check the actual type but only the id (on OSX/libc++).
In particular only the WinAPI and the ICU backends implement that facet and you don't even have either build which explains this.

So in a semi-correct version your use of std::use_facet<boost::locale::collator<char>> should throw a std::bad_cast. At least until the Posix and Std backends implement that facet which I don't think is possible.