[webkit-dev] Fix for WebCore's base64Decode...

Paul Pedriana ppedriana at gmail.com
Fri Dec 12 00:03:04 PST 2008


I see this in curl and soup code:

        // Use the GLib Base64 if available, since WebCore's decoder isn't
        // general-purpose and fails on Acid3 test 97 (whitespace).

In WebCore's base64Decode, I see this:

    for (unsigned idx = 0; idx < len; idx++) {
        unsigned char ch = data[idx];
        if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || (ch > 96 && 
ch < 123) || ch == '+' || ch == '/' || ch == '=')
            out[idx] = base64DecMap[ch];
        else
            return false;                                       <--- it 
shouldn't be doing this
    }

RFC 2045 states:
    All line breaks or other characters not found in Table 1 must
    be ignored by decoding software.

Thus can't WebCore's base64Decode be fixed simply like so, which works 
as expected in my tests:

bool base64Decode(const char* data, unsigned len, Vector<char>& out)
{
    out.clear();
    if (len == 0)
        return true;

    while (len && data[len-1] == '=')
        --len;

    out.grow(len);
    unsigned outSize = 0;
    for (unsigned idx = 0; idx < len; idx++) {
        unsigned char ch = data[idx];
        if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || (ch > 96 && 
ch < 123) || ch == '+' || ch == '/' || ch == '=') {
            out[outSize] = base64DecMap[ch];
            outSize++;
        }
    }

    out.resize(static_cast<size_t>(outSize));

    // 4-byte to 3-byte conversion
    unsigned outLen = outSize - ((outSize + 3) / 4);
    if (!outLen || ((outLen + 2) / 3) * 4 < outSize)
        return false;

    unsigned sidx = 0;
    unsigned didx = 0;
    if (outLen > 1) {
        while (didx < outLen - 2) {
            out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 
4) & 003));
            out[didx + 1] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 
2] >> 2) & 017));
            out[didx + 2] = (((out[sidx + 2] << 6) & 255) | (out[sidx + 
3] & 077));
            sidx += 4;
            didx += 3;
        }
    }

    if (didx < outLen)
        out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 
003));

    if (++didx < outLen)
        out[didx] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 
2) & 017));

    if (outLen < out.size())
        out.shrink(outLen);

    return true;
}

Is this all there is to the bug or is there more that I'm not aware of?

Thanks.

Paul










More information about the webkit-dev mailing list