Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

descriptor_parse: crash with whitespace on pk() #72

Open
brunoerg opened this issue Dec 23, 2024 · 6 comments
Open

descriptor_parse: crash with whitespace on pk() #72

brunoerg opened this issue Dec 23, 2024 · 6 comments
Labels

Comments

@brunoerg
Copy link
Owner

The following descriptor tr(03d1d1110030000000000120000000000000000000000000001370010912cd08cc,pk( L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)) fails to be parsed on rust-miniscript (key too short) and is successfully parsed on Bitcoin Core.

There is a whitespace on pk, instead of pk(KEY) is pk( KEY) which may cause this issue.

@brunoerg brunoerg added the crash label Dec 23, 2024
@apoelstra
Copy link

I think this is a bug in Core.

@brunoerg
Copy link
Owner Author

I think this is a bug in Core.

Yes. Will check it better and open an issue there.

@brunoerg
Copy link
Owner Author

brunoerg commented Dec 24, 2024

DecodeBase58 from Bitcoin Core skips leading spaces. The decode function fromrust-bitcoin does not.

[[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
{
    // Skip leading spaces.
    while (*psz && IsSpace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        if (zeroes > max_ret_len) return false;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
    std::vector<unsigned char> b256(size);
    // Process the characters.
    static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
    while (*psz && !IsSpace(*psz)) {
        // Decode base58 character
        int carry = mapBase58[(uint8_t)*psz];
        if (carry == -1)  // Invalid b58 character
            return false;
        int i = 0;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        if (length + zeroes > max_ret_len) return false;
        psz++;
    }
    // Skip trailing spaces.
    while (IsSpace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

@apoelstra
Copy link

Hmm. Ok, I continue to maintain that this is a bug in Core, but it seems like it might be by design.

@brunoerg
Copy link
Owner Author

Hmm. Ok, I continue to maintain that this is a bug in Core, but it seems like it might be by design.

Yes, I agree. Just was trying to understand what is the cause.

@brunoerg
Copy link
Owner Author

brunoerg commented Jan 4, 2025

Opened bitcoin/bitcoin#31603 to fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants