Steps to reproduce:

* Build with `integer` sanitizer
* Start: `UBSAN_OPTIONS="suppressions=$(pwd)/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1" ./src/qt/bitcoin-qt -chain=main`
* Enter `getdescriptorinfo "sh(multi(1,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/5/5/5/2/8/5/8/8/8/2/2/5/8/5/2/5/85/58/5/2/5/5/5/5/2/58/2/5/8/0000/00/8/5/2/001/1/246/8/501/46/8/5/8/5/000/8/52/5/8/5/2/8/2/5/8/5/246/8/5/2/8/2/5/8/5/2/5/8/8/2/5/5/5/58/88/2/6/8/5/2/8/2/5/8/2/588/5/2/5/8/5/2/8/5/1/5/4/5/5/5/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/8/58/588/2/52/5/5/5/58/8/2/6/8/5/2/8/2/5/8/2/588/5/2/5/8/5/2/8/5/15/58/58/2/6/8/5/2/8/2/5/8/5/2/5/8/58/2/5/58/58/588/2/5/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8/2/8/5/2/8/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/8/588/2/6/8/5/2/8/2/5/5/8/5/2/0/8/5/2/00/4/5/5/588/2/6/8/5/2/8/25/5/8/2/5/58/58/8/4/1,[00000000]xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/58)0)"` into the console
{
    /** A character set designed such that:
     *  - The most common 'unprotected' descriptor characters (hex, keypaths) are in the first group of 32.
     *  - Case errors cause an offset that's a multiple of 32.
     *  - As many alphabetic characters are in the same group (while following the above restrictions).
     *
     * If p(x) gives the position of a character c in this character set, every group of 3 characters
     * (a,b,c) is encoded as the 4 symbols (p(a) & 31, p(b) & 31, p(c) & 31, (p(a) / 32) + 3 * (p(b) / 32) + 9 * (p(c) / 32).
     * This means that changes that only affect the lower 5 bits of the position, or only the higher 2 bits, will just
     * affect a single symbol.
     *
     * As a result, within-group-of-32 errors count as 1 symbol, as do cross-group errors that don't affect
     * the position within the groups.
     */
    static std::string INPUT_CHARSET =
        "0123456789()[],'/*abcdefgh@:$%{}"
        "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
        "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
    
    static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
    uint64_t c = 1;
    int cls = 0;
    int clscount = 0;
    for (auto ch : span) {
        auto pos = INPUT_CHARSET.find(ch);
        if (pos == std::string::npos) return "";
        c = PolyMod(c, pos & 31);