zlib 解压 git pack 时错误的标头检查

问题描述 投票:0回答:1

我正在尝试解析我通过 POST 收到的 git 包

https://github.com/codecrafters-io/git-sample-3/git-upload-pack
数据是
0032want 23f0bc3b5c7c3108e41c448f01a3db31e7064bbb\n00000009done
并将返回的字符串存储在
std::string pack
中。为了解析字符串,我执行了以下操作

    pack = pack.substr(20, pack.length() - 40); // skip 8 byte http header, 12 byte pack header, 20 byte pack trailer
    int type;
    int pos = 0;
    std::string lengthstr;
    int length = 0;
    type = (pack[pos] & 112) >> 4; // 112 is 11100000 so this gets the first 3 bits
    length = length | (pack[pos] & 0x0F); // take the last 4 bits
    if (pack[pos] & 0x80) { // if the type bit starts with 0 then the last 4 bits are simply the length
        pos++;
        while (pack[pos] & 0x80) { // while leftmost bit is 1
            length = length << 7;
            length = length | (pack[pos] & 0x7F); // flip first bit to 0 si it's ignored, then we append the other 7 bits to the integer
            pos++;
        }
        length = length << 7;
        length = length | pack[pos]; // set the leftmost bit to 1 so it's ignored, and do the same thing
    }
    pos++;
    FILE* customStdout = fdopen(1, "w");

    FILE* source = fmemopen((void*)pack.substr(pos, length).c_str(), length, "r");
    std::cout << inf(source, customStdout) << "\n";

inf 来自 zpipe.c。 inf 调用结果为

Z_DATA_ERROR
,消息为
incorrect header check

我实际上以二进制形式打印了这些位,从 pos 开始的位是我对 zlib 标头的期望(

78 9C
),所以我不确定为什么我在这里得到不正确的标头。

我还尝试使用

inflateInit2(&strm, -MAX_WBITS)
并向 pos 添加 2 来完全跳过标题,但它返回相同的错误并显示消息
invalid stored block lengths

c++ git compression zlib
1个回答
0
投票

用以下代码替换

inf
调用

    int ret;
    unsigned have;
    z_stream strm;
    unsigned char in[16384];
    unsigned char out[16384];

    /* allocate inflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    strm.avail_in = pack.length() - pos;
    for (int i = 0; i < 16384; i++) {
        in[i] = pack[pos + i];
    }
    strm.next_in = in;
    strm.avail_out = 16384;
    strm.next_out = out;
    inflate(&strm, Z_NO_FLUSH);

允许 inflate 调用成功。我观察到的唯一区别是我将 pack 中的字符直接复制到流缓冲区中。我怀疑这个问题与我创建文件的方式有关

© www.soinside.com 2019 - 2024. All rights reserved.