一个用了两年多的lzo压缩代码,竟然有问题.

一个短短的lzo代码,我使用了两年
今天才发现它有问题,我平时也用zlib和7zip的压缩

这两天编译64位版本,lzo运行就直接崩了,发现它没有考虑到数据类型,并且,它竟然没有初始化应该初始化的数据!

#include "lzo.h"

UINT _do_compress(BYTE *in, UINT in_len, BYTE *out, UINT *out_len, BYTE *buffer)
{
    BYTE *ip;
    BYTE *op;
    BYTE *in_end = in + in_len;
    BYTE *ip_end = in + in_len - 13;
    BYTE *ii;
    UINT *dict = (UINT *)buffer;
    BYTE *p;    // xy添加的
    UINT m_pos;
    UINT m_off;
    UINT m_len;
    UINT dindex;
    UINT t;
    UINT tt;
    BYTE *end;
    BYTE *m;

    op = out;
    ip = in;
    ii = ip;

    ip += 4;

    for (t = 0; t < 0x4000; t++)
    {
        dict[t] = 0xffffffff;
    }

    for (;;)
    {
        dindex = ((0x21 * (((((((UINT)(ip[3]) << 6) ^ ip[2]) << 5) ^ ip[1]) << 5) ^ ip[0])) >> 5) & 0x3fff;
        m_pos = dict[dindex];

        if (m_pos == 0xffffffff || (m_off = (UINT)(ip - in - m_pos)) == 0 || m_off > 0xbfff)
            goto literal;

        p = in + m_pos;
        if (m_off <= 0x0800 || p[3] == ip[3])
            goto try_match;

        dindex = (dindex & 0x7ff) ^ 0x201f;

        m_pos = dict[dindex];
        if (m_pos == 0xffffffff || (m_off = (UINT)(ip - in - m_pos)) == 0 || m_off > 0xbfff)
            goto literal;
        p = in + m_pos;
        if (m_off <= 0x0800 || p[3] == ip[3])
            goto try_match;

        goto literal;

    try_match:
        p = in + m_pos;
        if (*(USHORT*)p == *(USHORT *)ip && p[2] == ip[2])
            goto match;

        literal:
        dict[dindex] = ip - in;
        ++ip;
        if (ip >= ip_end)
            break;
        continue;

    match:
        dict[dindex] = ip - in;
        if (ip - ii > 0)
        {
            t = ip - ii;

            if (t <= 3)
            {
                op[-2] |= (BYTE)t;
            }
            else if (t <= 18)
            {
                *op++ = (BYTE)(t - 3);
            }
            else
            {
                tt = t - 18;
                *op++ = 0;
                while (tt > 255)
                {
                    tt -= 255;
                    *op++ = 0;
                }
                *op++ = (BYTE)tt;
            }
            do *op++ = *ii++; while (--t > 0);
        }

        ip += 3;

        p = in + m_pos;
        if (p[3] != *ip++ || p[4] != *ip++ || p[5] != *ip++ ||
            p[6] != *ip++ || p[7] != *ip++ || p[8] != *ip++)
        {
            --ip;
            m_len = ip - ii;

            if (m_off <= 0x0800)
            {
                --m_off;
                *op++ = (BYTE)(((m_len - 1) << 5) | ((m_off & 7) << 2));
                *op++ = (BYTE)(m_off >> 3);
            }
            else
                if (m_off <= 0x4000)
                {
                    --m_off;
                    *op++ = (BYTE)(32 | (m_len - 2));
                    goto m3_m4_offset;
                }
                else
                {
                    m_off -= 0x4000;
                    *op++ = (BYTE)(16 | ((m_off & 0x4000) >> 11) | (m_len - 2));
                    goto m3_m4_offset;
                }
        }
        else
        {
            {
                end = in_end;
                m = p + 9;
                while (ip < end && *m == *ip)
                    m++, ip++;
                m_len = (ip - ii);
            }


            if (m_off <= 0x4000)
            {
                --m_off;
                if (m_len <= 33)
                    *op++ = (BYTE)(32 | (m_len - 2));
                else
                {
                    m_len -= 33;
                    *op++ = 32;
                    goto m3_m4_len;
                }
            }
            else
            {
                m_off -= 0x4000;
                if (m_len <= 9)
                    *op++ = (BYTE)(16 | ((m_off & 0x4000) >> 11) | (m_len - 2));
                else
                {
                    m_len -= 9;
                    *op++ = (BYTE)(16 | ((m_off & 0x4000) >> 11));
                m3_m4_len:
                    while (m_len > 255)
                    {
                        m_len -= 255;
                        *op++ = 0;
                    }
                    *op++ = (BYTE)m_len;
                }
            }

        m3_m4_offset:
            *op++ = (BYTE)((m_off & 63) << 2);
            *op++ = (BYTE)(m_off >> 6);
        }

        ii = ip;
        if (ip >= ip_end)
            break;
    }

    *out_len = op - out;
    return (UINT)(in_end - ii);
}

UINT WINAPI lzo_compress(void *in, UINT in_len, void *out, BYTE *buffer)
{
    BYTE *op = (BYTE *)out;
    UINT t, out_len;
    UINT tt;
    BYTE *ii;

    if (in_len <= 13)
        t = in_len;
    else
    {
        t = _do_compress((BYTE *)in, in_len, (BYTE *)op, &out_len, buffer);
        op += out_len;
    }

    if (t > 0)
    {
        ii = (BYTE*)in + in_len - t;
        if (op == (BYTE*)out && t <= 238)
            *op++ = (BYTE)(17 + t);
        else
            if (t <= 3)
                op[-2] |= (BYTE)t;
            else
                if (t <= 18)
                    *op++ = (BYTE)(t - 3);
                else
                {
                    tt = t - 18;

                    *op++ = 0;
                    while (tt > 255)
                    {
                        tt -= 255;
                        *op++ = 0;
                    }
                    *op++ = (BYTE)tt;
                }
        do *op++ = *ii++; while (--t > 0);
    }

    *op++ = 17;
    *op++ = 0;
    *op++ = 0;

    return (op - (BYTE*)out);
}

UINT WINAPI lzo_decompress(void *in, UINT in_len, void *out)
{
    BYTE *op;
    BYTE *ip;
    UINT t;
    BYTE *m_pos;
    BYTE *ip_end;

    ip_end = (BYTE*)in + in_len;

    op = (BYTE *)out;
    ip = (BYTE *)in;

    if (*ip > 17)
    {
        t = *ip++ - 17;
        if (t < 4)
            goto match_next;
        do *op++ = *ip++; while (--t > 0);
        goto first_literal_run;
    }

    for (;;)
    {
        t = *ip++;
        if (t >= 16) goto match;
        if (t == 0)
        {
            while (*ip == 0)
            {
                t += 255;
                ip++;
            }
            t += 15 + *ip++;
        }

        *(UINT *)op = *(UINT *)ip;
        op += 4; ip += 4;
        if (--t > 0)
        {
            if (t >= 4)
            {
                do
                {
                    *(UINT *)op = *(UINT *)ip;
                    op += 4; ip += 4; t -= 4;
                } while (t >= 4);
                if (t > 0) do *op++ = *ip++; while (--t > 0);
            }
            else
                do *op++ = *ip++; while (--t > 0);
        }

    first_literal_run:

        t = *ip++;
        if (t >= 16)
            goto match;

        m_pos = op - 0x0801;
        m_pos -= t >> 2;
        m_pos -= *ip++ << 2;

        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;

        goto match_done;

        for (;;)
        {
        match:
            if (t >= 64)
            {

                m_pos = op - 1;
                m_pos -= (t >> 2) & 7;
                m_pos -= *ip++ << 3;
                t = (t >> 5) - 1;

                goto copy_match;

            }
            else
                if (t >= 32)
                {
                    t &= 31;
                    if (t == 0)
                    {
                        while (*ip == 0)
                        {
                            t += 255;
                            ip++;
                        }
                        t += 31 + *ip++;
                    }

                    m_pos = op - 1;
                    m_pos -= (*(USHORT *)ip) >> 2;
                    ip += 2;
                }
                else
                    if (t >= 16)
                    {
                        m_pos = op;
                        m_pos -= (t & 8) << 11;
                        t &= 7;
                        if (t == 0)
                        {
                            while (*ip == 0)
                            {
                                t += 255;
                                ip++;
                            }
                            t += 7 + *ip++;
                        }
                        m_pos -= (*(USHORT *)ip) >> 2;
                        ip += 2;
                        if (m_pos == op)
                            goto eof_found;
                        m_pos -= 0x4000;
                    }
                    else
                    {
                        m_pos = op - 1;
                        m_pos -= t >> 2;
                        m_pos -= *ip++ << 2;
                        *op++ = *m_pos++; *op++ = *m_pos;
                        goto match_done;
                    }

            if (t >= 6 && (op - m_pos) >= 4)
            {
                *(UINT *)op = *(UINT *)m_pos;
                op += 4; m_pos += 4; t -= 2;
                do
                {
                    *(UINT *)op = *(UINT *)m_pos;
                    op += 4; m_pos += 4; t -= 4;
                } while (t >= 4);
                if (t > 0)
                    do *op++ = *m_pos++; while (--t > 0);
            }
            else
            {
            copy_match:
                *op++ = *m_pos++; *op++ = *m_pos++;
                do *op++ = *m_pos++; while (--t > 0);
            }

        match_done:
            t = ip[-2] & 3;
            if (t == 0)    break;

        match_next:
            do *op++ = *ip++; while (--t > 0);
            t = *ip++;
        }
    }

eof_found:
    if (ip != ip_end) return -1;
    return (op - (BYTE*)out);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值