On Tue, Jun 02, 2026 at 07:25:39AM +0200, Theo Buehler wrote:
> 
> On Tue, Jun 02, 2026 at 01:10:45PM +0800, Kevin Lo wrote:
> > On Sun, May 31, 2026 at 07:15:57PM +0200, Christian Weisgerber wrote:
> > > 
> > > http://build-failures.rhaalovely.net/amd64/2026-05-30/
> > 
> > [snip]
> > 
> > > inputmethods/libime                 ports@
> > 
> > Use -O1 on datrie.cpp otherwise build fails with SIGSEGV in 
> > libime_prediction.
> 
> This seems to be resolved via https://github.com/fcitx/libime/pull/99
> At least the below backport of that PR builds on amd64.
> 
> Even better would be an update to >= 1.1.11.

Thanks, this looks much better than mine.
Tested on amd64, builds and works.

> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/inputmethods/libime/Makefile,v
> diff -u -p -r1.13 Makefile
> --- Makefile  23 Mar 2026 06:22:51 -0000      1.13
> +++ Makefile  2 Jun 2026 05:22:25 -0000
> @@ -1,7 +1,7 @@
>  COMMENT =    library to support generic input method implementation
>  
>  DISTNAME =   libime-1.1.9
> -REVISION =   3
> +REVISION =   4
>  
>  SHARED_LIBS +=       IMECore         0.2 # 0.0
>  SHARED_LIBS +=       IMEPinyin       0.2 # 0.0
> Index: patches/patch-src_libime_core_datrie_cpp
> ===================================================================
> RCS file: patches/patch-src_libime_core_datrie_cpp
> diff -N patches/patch-src_libime_core_datrie_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_libime_core_datrie_cpp  2 Jun 2026 05:22:22 -0000
> @@ -0,0 +1,172 @@
> +Avoid UB breaking the build with llvm22
> +
> +https://github.com/fcitx/libime/pull/99
> +
> +Index: src/libime/core/datrie.cpp
> +--- src/libime/core/datrie.cpp.orig
> ++++ src/libime/core/datrie.cpp
> +@@ -23,7 +23,9 @@
> + #include <fstream>
> + #include <ios>
> + #include <istream>
> ++#include <iterator>
> + #include <limits>
> ++#include <optional>
> + #include <ostream>
> + #include <stdexcept>
> + #include <string>
> +@@ -96,7 +98,8 @@ class DATriePrivate { (public)
> +     static inline const int32_t CEDAR_NO_VALUE = NanValue<V>::NO_VALUE();
> +     static inline const int32_t CEDAR_NO_PATH = NanValue<V>::NO_PATH();
> + 
> +-    static constexpr int MAX_ALLOC_SIZE = 1 << 16; // must be divisible by 
> 256
> ++    static constexpr size_t MAX_ALLOC_SIZE = 1
> ++                                             << 16; // must be divisible by 
> 256
> +     using result_type = value_type;
> +     using uchar = uint8_t;
> +     static_assert(sizeof(value_type) <= sizeof(int32_t),
> +@@ -481,10 +484,7 @@ class DATriePrivate { (public)
> +         if (m_tail.capacity() < m_tail.size() + needed) {
> +             auto quota =
> +                 m_tail.capacity() +
> +-                ((needed > m_tail.size() || needed > MAX_ALLOC_SIZE)
> +-                     ? needed
> +-                     : (m_tail.size() >= MAX_ALLOC_SIZE ? MAX_ALLOC_SIZE
> +-                                                        : m_tail.size()));
> ++                std::max(needed, std::min(MAX_ALLOC_SIZE, m_tail.size()));
> +             m_tail.reserve(quota);
> +         }
> +         m_array[from].base = -m_tail.size();
> +@@ -592,8 +592,11 @@ class DATriePrivate { (public)
> +             npos.offset ? -static_cast<int>(npos.offset) : 
> m_array[from].base;
> +         if (base >= 0) { // on trie
> +             uchar c = m_ninfo[from].child;
> +-            if (!from && !(c = m_ninfo[base ^ c].sibling)) { // bug fix
> +-                return CEDAR_NO_PATH;                        // no entry
> ++            if (!from) {
> ++                c = m_ninfo[base ^ c].sibling;
> ++                if (!c) {                 // bug fix
> ++                    return CEDAR_NO_PATH; // no entry
> ++                }
> +             }
> +             for (; c && base >= 0; ++len) {
> +                 from = static_cast<size_t>(base) ^ c;
> +@@ -638,11 +641,13 @@ class DATriePrivate { (public)
> +     int _follow(uint32_t &from, const uchar label, const T &cf) {
> +         int to = 0;
> +         const int base = m_array[from].base;
> +-        if (base < 0 || m_array[to = base ^ label].check < 0) {
> ++        if (base < 0 || m_array[base ^ label].check < 0) {
> +             to = _pop_enode(base, label, static_cast<int>(from));
> +             _push_sibling(from, to ^ label, label, base >= 0);
> +-        } else if (m_array[to].check != static_cast<int>(from)) {
> ++        } else if (m_array[base ^ label].check != static_cast<int>(from)) {
> +             to = _resolve(from, base, label, cf);
> ++        } else {
> ++            to = base ^ label;
> +         }
> +         return to;
> +     }
> +@@ -707,7 +712,7 @@ class DATriePrivate { (public)
> +     int _find_place(const uchar *const first, const uchar *const last) {
> +         if (auto bi = m_bheadO) {
> +             const auto bz = m_block[m_bheadO].prev;
> +-            const auto nc = static_cast<short>(last - first + 1);
> ++            const auto nc = std::distance(first, last);
> +             while (true) { // set candidate block
> +                 block &b = m_block[bi];
> +                 if (b.num >= nc && nc < b.reject) { // explore configuration
> +@@ -715,11 +720,13 @@ class DATriePrivate { (public)
> +                         const int base = e ^ *first;
> +                         for (const uchar *p = first;
> +                              m_array[base ^ *++p].check < 0;) {
> +-                            if (p == last) {
> +-                                return b.ehead = e; // no conflict
> ++                            if (p + 1 == last) {
> ++                                b.ehead = e;
> ++                                return b.ehead; // no conflict
> +                             }
> +                         }
> +-                        if ((e = -m_array[e].check) == b.ehead) {
> ++                        e = -m_array[e].check;
> ++                        if (e == b.ehead) {
> +                             break;
> +                         }
> +                     }
> +@@ -892,23 +899,27 @@ class DATriePrivate { (public)
> +         return c_p;
> +     }
> +     // enumerate (equal to or more than one) child nodes
> +-    uchar *_set_child(uchar *p, const int base, uchar c, const int label = 
> -1) {
> +-        --p;
> ++    uchar *_set_child(uchar *p, const int base, uchar c,
> ++                      const std::optional<uchar> label = std::nullopt) {
> +         if (!c) {
> +-            *++p = c;
> ++            *p = c;
> ++            p++;
> +             c = m_ninfo[base ^ c].sibling;
> +         } // 0: terminal
> +-        if (ORDERED) {
> +-            while (c && c < label) {
> +-                *++p = c;
> ++        if (ORDERED && label.has_value()) {
> ++            while (c && c < *label) {
> ++                *p = c;
> ++                p++;
> +                 c = m_ninfo[base ^ c].sibling;
> +             }
> +         }
> +-        if (label != -1) {
> +-            *++p = static_cast<uchar>(label);
> ++        if (label.has_value()) {
> ++            *p = *label;
> ++            p++;
> +         }
> +         while (c) {
> +-            *++p = c;
> ++            *p = c;
> ++            p++;
> +             c = m_ninfo[base ^ c].sibling;
> +         }
> +         return p;
> +@@ -925,30 +936,33 @@ class DATriePrivate { (public)
> +             = _consult(base_n, base_p, m_ninfo[from_n].child,
> +                        m_ninfo[from_p].child);
> +         uchar child[256];
> +-        uchar *const first = &child[0];
> ++        uchar *const first = child;
> +         uchar *const last =
> +             flag ? _set_child(first, base_n, m_ninfo[from_n].child, label_n)
> +                  : _set_child(first, base_p, m_ninfo[from_p].child);
> ++        assert(first < last);
> +         const int base =
> +-            (first == last ? _find_place() : _find_place(first, last)) ^ 
> *first;
> ++            (first + 1 == last ? _find_place() : _find_place(first, last)) ^
> ++            *first;
> +         // replace & modify empty list
> +         const int from = flag ? static_cast<int>(from_n) : from_p;
> +         const int base_ = flag ? base_n : base_p;
> +         if (flag && *first == label_n) {
> +             m_ninfo[from].child = label_n; // new child
> +         }
> +-        m_array[from].base = base;                     // new base
> +-        for (const uchar *p = first; p <= last; ++p) { // to_ => to
> ++        m_array[from].base = base;                    // new base
> ++        for (const uchar *p = first; p < last; ++p) { // to_ => to
> +             const int to = _pop_enode(base, *p, from);
> +             const int to_ = base_ ^ *p;
> +-            m_ninfo[to].sibling = (p == last ? 0 : *(p + 1));
> ++            m_ninfo[to].sibling = (p + 1 == last) ? 0 : *(p + 1);
> +             if (flag && to_ == to_pn) {
> +                 continue; // skip newcomer (no child)
> +             }
> +             cf(to_, to);
> +             node &n = m_array[to];
> +             node &n_ = m_array[to_];
> +-            if ((n.base = n_.base) > 0 && *p) { // copy base; bug fix
> ++            n.base = n_.base; // copy base; bug fix
> ++            if (n.base > 0 && *p) {
> +                 uchar c = m_ninfo[to].child = m_ninfo[to_].child;
> +                 do {
> +                     m_array[n.base ^ c].check = to; // adjust grand son's 
> check
> 

Reply via email to