google / zopfli

Zopfli Compression Algorithm is a compression library programmed in C to perform very good, but slow, deflate or zlib compression.
Apache License 2.0
3.42k stars 326 forks source link

SIGBUS error on mips64el architecture #22

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I'm having a SIGBUS error with zopfli-1.0.0 on OpenBSD/loongson (which is a 
little-endian MIPS64 architecture, with strict alignment).

The following hello.c file:
#include <stdio.h>

int main(void)
{
    printf("hello, world\n");

    return 0;
}

triggers a SIGBUS error in zopfli:
$ zopfli hello.c
Starting program: /usr/local/bin/zopfli hello.c

Program received signal SIGBUS, Bus error.
0x0000000006987cb8 in ZopfliFindLongestMatch (s=0x7ffdca40, h=0x7ffdc988, 
    array=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", pos=40, size=78, limit=38, 
    sublen=0x7ffdc780, distance=0x7ffdc9d4, length=0x7ffdc9d6)
    at src/zopfli/lz77.c:126
126     while (scan < safe_end && *((size_t*)scan) == *((size_t*)match)) {
#0  0x0000000006987cb8 in ZopfliFindLongestMatch (s=0x7ffdca40, h=0x7ffdc988, 
    array=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", pos=40, size=78, limit=38, 
    sublen=0x7ffdc780, distance=0x7ffdc9d4, length=0x7ffdc9d6)
    at src/zopfli/lz77.c:126
    same0 = Variable "same0" is not available.
#0  0x0000000006987cb8 in ZopfliFindLongestMatch (s=0x7ffdca40, h=0x7ffdc988, 
    array=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", pos=40, size=78, limit=38, 
    sublen=0x7ffdc780, distance=0x7ffdc9d4, length=0x7ffdc9d6)
    at src/zopfli/lz77.c:126
#1  0x0000000006988490 in ZopfliLZ77Greedy (s=0x7ffdca40, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", instart=1, inend=78, store=0x7ffdca60)
    at src/zopfli/lz77.c:399
#2  0x0000000006982d78 in ZopfliBlockSplit (options=0x7ffdcd90, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", instart=0, inend=78, maxblocks=15, 
    splitpoints=0x7ffdcb00, npoints=0x7ffdcaf8)
    at src/zopfli/blocksplitter.c:310
#3  0x00000000069855f4 in DeflateSplittingFirst (options=0x7ffdcd90, btype=2, 
    final=1, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", instart=0, inend=78, bp=0x7ffdccd7 "", 
    out=0x7ffdcdb0, outsize=0x7ffdcda8) at src/zopfli/deflate.c:569
#4  0x0000000006985904 in ZopfliDeflatePart (options=0x7ffdcd90, btype=2, 
    final=1, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", instart=0, inend=78, bp=0x7ffdccd7 "", 
    out=0x7ffdcdb0, outsize=0x7ffdcda8) at src/zopfli/deflate.c:668
#5  0x0000000006985adc in ZopfliDeflate (options=0x7ffdcd90, btype=2, final=1, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", insize=78, bp=0x7ffdccd7 "", out=0x7ffdcdb0, 
    outsize=0x7ffdcda8) at src/zopfli/deflate.c:687
#6  0x0000000006985ef8 in ZopfliGzipCompress (options=0x7ffdcd90, 
    in=0x5336c200 "#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"hello, world\\n\");\n\n\treturn 0;\n}\n", insize=78, out=0x7ffdcdb0, outsize=0x7ffdcda8)
    at src/zopfli/gzip_container.c:96
#7  0x000000000698b52c in ZopfliCompress (options=Variable "options" is not 
available.
) at src/zopfli/zopfli_lib.c:33
#8  0x000000000698b174 in main (argc=2, argv=0x7ffdce60)
    at src/zopfli/zopfli_bin.c:96

Original issue reported on code.google.com by tso...@gmail.com on 22 Jun 2013 at 11:37

GoogleCodeExporter commented 9 years ago
> while (scan < safe_end && *((size_t*)scan) == *((size_t*)match)) {

If scan is not integer aligned, then that will cause unaligned accesses. In 
x86, this is a performance problem. In other architectures, it results in a 
SIGBUS like you are seeing.

It seems to me that there should be a bit of code before the while loop that 
advances scan up to the next alignment boundary, like you find in optimized 
memcmp implementations. Once scan is aligned, then the optimized loops (for 8 
and 4 bytes) can be used.

Original comment by jeff.al...@gmail.com on 10 Jan 2014 at 12:56

jibsen commented 8 years ago

Compiling with -fsanitize=undefined results in runtime errors for these unaligned reads. I believe it could also potentially be violating the strict aliasing rule.