You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现的RLE二进制文件压缩解压功能偶发故障求助

排查出的bug及修复方案
  • 解压函数边界逻辑错误
    RLEdecompress中循环写入的判断条件retIdx < compressedSize完全错误,compressedSize是压缩后的文件大小,解压写入的上限应该是传入的uncompressedSize参数,错误的边界会导致解压时提前终止写入或者写入逻辑异常。
  • 二进制文件使用文本模式读写
    所有fopen调用均使用了r/w文本模式,在Windows平台下文本模式会自动做换行符(0x0A与0x0D0A)的转换,且遇到0x1A字节会判定为文件结束提前终止读取。PDF是二进制格式,文件中存在大量非文本字节,只有碰到特殊字节时才会触发问题,这就是bug偶发的核心原因。
  • 解压逻辑存在越界访问风险
    当inIdx已经走到压缩数据的最后一个位置(等于compressedSize-1)时,data[inIdx] == data[inIdx + 1]的判断会访问缓冲区外的内存,属于未定义行为,若读到的垃圾值恰好等于当前字节,就会误判为连续重复标记,导致额外多出重复字节。

修复要点

  1. 所有二进制文件的fopen调用替换为二进制模式:把r改为rb,w改为wb,示例:
FILE* fp = fopen(argv[1], "rb");
FILE* fpcompWrite = fopen("compressed", "wb+");
FILE* fpcompRead = fopen("compressed", "rb");
FILE* funcomp = fopen("uncompressed", "wb+");
  1. 修改RLEdecompress函数的错误逻辑,修复后的代码如下:
char* RLEdecompress(char* data, size_t compressedSize, size_t uncompressedSize, size_t extraAllocation) {
    char* ret = calloc(uncompressedSize + extraAllocation, 1);
    size_t retIdx = 0, inIdx = 0;
    while (inIdx < compressedSize) {
        ret[retIdx++] = data[inIdx];
        // 先判断不会越界再做后续判断
        if (inIdx + 1 < compressedSize && data[inIdx] == data[inIdx + 1]) { 
            size_t occ = ((data[inIdx + 2]) - '0');
            // 边界改为uncompressedSize
            for (size_t i = 1; i < occ && retIdx < uncompressedSize; i++) {
                ret[retIdx++] = data[inIdx];
            }
            inIdx += 2;
        }
        inIdx += 1;
    }
    return ret;
}

内容的提问来源于stack exchange,提问作者Samuele B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 12:27:04