Skip to content

Segfault in Bt3Zip_MatchFinder_GetMatches2 on all PNG files when compression level >= 2 and compiled with GCC 15 with -O3 or higher #145

Description

@lmfont

I've been using ect for years on this system, with no issue, but recently all PNG files starting crashing ect. I don't see a crash when ect is compiled with clang 20.1.8 or gcc 14.3.1. The system version of gcc is 15.1.1, and using it results in a segfault.

Optimizing at -O2 does not cause the segfault, optimizing at -O3 does.

Backtrace:

#0  0x0000555555563629 in Bt3Zip_MatchFinder_GetMatches2 ()
#1  0x00005555555a3e35 in GetBestLengths.isra.0 ()
#2  0x00005555555a4c61 in ZopfliLZ77Optimal2 ()
#3  0x000055555559e9aa in ZopfliDeflate ()
#4  0x0000555555564426 in CustomPNGDeflate(unsigned char**, unsigned long*, unsigned char const*, unsigned long, LodePNGCompressSettings const*) ()
#5  0x0000555555578f85 in lodepng_zlib_compress(unsigned char**, unsigned long*, unsigned char const*, unsigned long, LodePNGCompressSettings const*) [clone .constprop.0] ()
#6  0x0000555555581b0f in lodepng_encode(unsigned char**, unsigned long*, unsigned char const*, unsigned int, unsigned int, LodePNGState*, LodePNGPaletteSettings) ()
#7  0x000055555558e010 in lodepng::encode(std::vector<unsigned char, std::allocator<unsigned char> >&, unsigned char const*, unsigned long, unsigned int, unsigned int, lodepng::State&, LodePNGPaletteSettings) ()
#8  0x000055555556500b in Zopflipng(bool, char const*, bool, unsigned int, int, unsigned int, unsigned int) ()
#9  0x000055555555e00e in fileHandler(char const*, ECTOptions const&, int) ()
#10 0x000055555555b9b3 in main ()

Activity

  1. xBZZZZ commented on Aug 16, 2025

    @xBZZZZ

    patch

    you need to download ect-gcc-15-O3-fix.patch, copy+paste test below into file won't work because LzFind.c contains U+000D CARRIAGE RETURN (CR) characters

    diff --git a/src/LzFind.c b/src/LzFind.c
    index 98d0ac6..f1bee55 100755
    --- a/src/LzFind.c
    +++ b/src/LzFind.c
    @@ -229,7 +229,7 @@ static unsigned short * GetMatches2(UInt32 lenLimit, UInt32 curMatch, UInt32 pos
         const unsigned char* _min = min;
         unsigned cnt = 0;
         if (_min < pb - (rle_len - len)) {_min = pb - (rle_len - len);}
    -    while (rle_pos > _min && *(uint64_t*)(rle_pos - 8) == starter_full) {rle_pos-=8; cnt+=8;}
    +    while (rle_pos > _min && *(__typeof__(const uint64_t __attribute__((aligned(1))))*)(rle_pos - 8) == starter_full) {rle_pos-=8; cnt+=8;}
         if (cnt) {
           if (cnt + len > rle_len - 1) {cnt = rle_len - 1 - len;}
           curMatch_rle -= cnt;
  2. fhanau commented on Jul 18, 2026

    @fhanau
    Owner

    I can't reproduce this issue on arm64 macOS using GCC 15.3.0 or 16.1.0 with the PNG file linked in #155 or with other PNG files. I assume that the issue is either limited to x64 (assuming that that's your platform), or to Linux (don't see how), or it already got fixed sometime after 15.1.1. Can you check if this is still happening with later GCC versions on your system?

  3. fhanau commented on Aug 2, 2026

    @fhanau
    Owner

    Closing for now – feel free to reopen if you can provide an image that reproduces this for ECT compiled with GCC 15.3.0 or 16.1.0.

  4. chenxiaolong commented on Aug 2, 2026

    @chenxiaolong

    I'm not the original reporter, but I can reproduce this with ect built from commit e420a6e with gcc-16.1.1-2.fc44.x86_64 (Linux, Fedora 44 x86_64). The patch from #145 (comment) does avoid the crash on my system.

    I used this image for testing: Screenshot_20260727-093955.zip. It's zipped in case Github recompresses the file.

    I compiled ect with cmake ../src -DCMAKE_BUILD_TYPE=RelWithDebInfo and ran it with:

    ❯ ect -9 -strip Screenshot_20260727-093955.png 
    zsh: segmentation fault (core dumped)  ect -9 -strip Screenshot_20260727-093955.png

    Under gdb:

    (gdb) bt
    #0  0x000000000040a57d in GetMatches2 (lenLimit=258, curMatch=36797, pos=40577, cur=0x109e201 '\352' <repeats 199 times>, <incomplete sequence \352>..., son=0x81a390, _cyclicBufferPos=<optimized out>, distances=0x7ffffffc61a4)
        at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/LzFind.c:232
    #1  Bt3Zip_MatchFinder_GetMatches2 (p=p@entry=0x7ffffffc6630, distances=distances@entry=0x7ffffffc61a0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/LzFind.c:349
    #2  0x000000000044c42f in GetBestLengths (in=in@entry=0x109c380 "", instart=instart@entry=0, inend=inend@entry=342486, costcontext=<optimized out>, length_array=length_array@entry=0x53d4a0, storeincache=storeincache@entry=0 '\000', c=<optimized out>, 
        mfinexport=<optimized out>, options=<optimized out>) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/squeeze.c:587
    #3  0x000000000044d0bd in LZ77OptimalRun (options=0x7fffffffc0a0, ultra2=0, in=<optimized out>, instart=<optimized out>, inend=<optimized out>, length_array=0x53d4a0, costcontext=<optimized out>, store=0x7fffffffbff0, storeincache=0 '\000', c=0x0, 
        mfinexport=<optimized out>) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/squeeze.c:898
    #4  ZopfliLZ77Optimal2 (options=<optimized out>, in=<optimized out>, instart=<optimized out>, inend=<optimized out>, store=<optimized out>, costmodelnotinited=<optimized out>, statsp=<optimized out>, mfinexport=<optimized out>)
        at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/squeeze.c:1225
    #5  0x000000000044720e in DeflateDynamicBlock (options=0x7fffffffc0a0, final=<optimized out>, in=<optimized out>, instart=<optimized out>, inend=342486, bp=<optimized out>, out=0x7fffffffc120, outsize=<optimized out>, costmodelnotinited=0x7fffffffbfb0 "\001\307P", 
        statsp=0x532f90, twiceMode=0 '\000', twiceStore=<optimized out>, mfinexport=2) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/deflate.cpp:1071
    #6  DeflateSplittingFirst (twiceMode=0 '\000', options=0x7fffffffc0a0, final=0, in=0x109c380 "", instart=<optimized out>, inend=<optimized out>, bp=<optimized out>, out=0x7fffffffc120, outsize=<optimized out>, costmodelnotinited=0x7fffffffbfb0 "\001\307P", 
        twiceStore=0x7fffffffbfd0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/deflate.cpp:1317
    #7  ZopfliDeflatePart (options=0x7fffffffc0a0, final=0, in=0x109c380 "", instart=<optimized out>, inend=<optimized out>, bp=<optimized out>, out=0x7fffffffc120, outsize=<optimized out>, costmodelnotinited=0x7fffffffbfb0 "\001\307P", twiceMode=0 '\000', 
        twiceStore=0x7fffffffbfd0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/deflate.cpp:1352
    #8  ZopfliDeflate (options=0x7fffffffc0a0, final=<optimized out>, in=0x109c380 "", insize=12066736, bp=0x7fffffffc09f "", out=0x7fffffffc120, outsize=0x7fffffffc128) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopfli/deflate.cpp:1389
    #9  0x000000000040b255 in CustomPNGDeflate (out=0x7fffffffc120, outsize=0x7fffffffc128, in=0x109c380 "", insize=12066736, settings=<optimized out>) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopflipng.cpp:68
    #10 0x0000000000420b64 in deflate (out=0x7fffffffc120, outsize=0x7fffffffc128, in=0x109c380 "", insize=12066736, settings=0x0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/lodepng/lodepng.cpp:369
    #11 lodepng_zlib_compress (out=out@entry=0x7fffffffc3f0, outsize=outsize@entry=0x7fffffffc480, in=0x109c380 "", insize=insize@entry=12066736, settings=settings@entry=0x7fffffffce60) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/lodepng/lodepng.cpp:428
    #12 0x0000000000429b0b in addChunk_IDAT (out=0x7fffffffc5d0, data=<optimized out>, datasize=12066736, zlibsettings=0x7fffffffce60) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/lodepng/lodepng.cpp:3121
    #13 lodepng_encode (out=out@entry=0x7fffffffca70, outsize=outsize@entry=0x7fffffffca78, 
        image=image@entry=0x7ffff6a1b010 "\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377"..., w=<optimized out>, h=<optimized out>, state=state@entry=0x7fffffffce50, palset=...) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/lodepng/lodepng.cpp:4321
    #14 0x0000000000436725 in lodepng::encode (out=std::vector of length 0, capacity 0, 
        in=in@entry=0x7ffff6a1b010 "\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377"..., insize=insize@entry=16084992, w=w@entry=1344, h=h@entry=2992, state=..., p=...) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/lodepng/lodepng.cpp:4611
    #15 0x000000000040bb69 in TryOptimize (
        image=0x7ffff6a1b010 "\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377\352\352\352\377"..., imagesize=16084992, w=1344, h=2992, bit16=false, inputstate=..., png_options=0x7fffffffcb90, out=0x7fffffffcc00, best_filter=0, filters=..., palette_filter=0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopflipng.cpp:384
    #16 ZopfliPNGOptimize (Infile=0x4f9040 "Screenshot_20260727-093955.png", origpng=std::vector of length 68241, capacity 68241 = {...}, png_options=..., resultpng=0x7fffffffcc00, best_filter=0, filters=..., palette_filter=0)
        at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopflipng.cpp:506
    #17 Zopflipng (strip=<optimized out>, Infile=Infile@entry=0x4f9040 "Screenshot_20260727-093955.png", strict=<optimized out>, Mode=Mode@entry=3, filter=filter@entry=0, multithreading=<optimized out>, quiet=0)
        at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/zopflipng.cpp:546
    #18 0x000000000040583a in OptimizePNG (Infile=0x4f9040 "Screenshot_20260727-093955.png", Options=...) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/main.cpp:190
    #19 fileHandler (Infile=0x4f9040 "Screenshot_20260727-093955.png", Options=..., internal=internal@entry=0) at /home/chenxiaolong/git/github/Efficient-Compression-Tool/src/main.cpp:318
    #20 0x0000000000402853 in main (argc=<optimized out>, argv=<optimized out>) at /usr/include/c++/16/bits/basic_string.h:237
    
  5. fhanau commented on Aug 2, 2026

    @fhanau
    Owner

    Tried to reproduce using the provided file and GCC on arm64 macOS, as well as using an x86_64 clang x86_64 binary using Rosetta – compression worked in both cases. I assume this only happens with GCC on x86_64, or only on Linux – I'll try to reproduce on a Linux machine but it'll take me longer to do that.

  6. reopened this on Aug 2, 2026
  7. zamadatix commented on Aug 28, 2026

    @zamadatix

    If it helps verify this assumption: I ran into this on GCC+x64+Linux+my own PNG file. Patch seemed to work fine. I did not run into the issue on x64 Windows Clang as far as I could tell, but I also didn't spend much time with it there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions