tkimg release 2.0.1
Running this under the Clang64 environment of MSYS2 (note that the clang64 environment is native Windows using UCRT, Universal C Runtime, which is the current C runtime of Microsoft).
# stack.tcl
puts stderr "starting..."
package require Img
image create photo milogo -file "cat.jpg"
puts "done"
exit
(replace "cat.jpg" with any jpg file)
$ wish stack.tcl
starting...
*** stack smashing detected ***: terminated
The tkimg package in the clang64 environment is built with the following flags, as displayed by tkimg's configure script:
Installation directory: /clang64
Documentation directory: ${prefix}/share/doc/tiff-4.7.0
C compiler: clang -march=nocona -msahf -mtune=generic -O2 -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wp,-D__USE_MINGW_ANSI_STDIO=1 -ggdb -Og -ffile-prefix-map=/d/dev/other/MINGW-packages/mingw-w64-tkimg/src=/clang64/src/debug/mingw-w64-tkimg -fsanitize=address -pipe -Wall -W
C++ compiler: clang++ -march=nocona -msahf -mtune=generic -O2 -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wp,-D__USE_MINGW_ANSI_STDIO=1 -ggdb -Og -ffile-prefix-map=/d/dev/other/MINGW-packages/mingw-w64-tkimg/src=/clang64/src/debug/mingw-w64-tkimg
Rebuilding with debug symbols and running under gdb shows this:
gdb: unknown target exception 0xc0000409 at 0x7fff2cc54327
Thread 1 received signal ?, Unknown signal.
0x00007fff2cc54327 in __fastfail (code=2) at C:/M/msys64/clang64/include/_mingw.h:632
warning: 632 C:/M/msys64/clang64/include/_mingw.h: No such file or directory
(gdb) bt
#0 0x00007fff2cc54327 in __fastfail (code=2) at C:/M/msys64/clang64/include/_mingw.h:632
#1 __stack_chk_fail () at C:/W/B/src/mingw-w64/mingw-w64-crt/ssp/stack_chk_fail.c:18
#2 0x00007fff2cc51ff1 in CommonMatch (png_ptr=0x0, handle=<optimized out>,
widthPtr=0x7fff2cc5d148 <__stack_chk_guard>, heightPtr=0x7fff2cc5431e <__stack_chk_fail+46>,
xdpiPtr=<optimized out>, ydpiPtr=<optimized out>) at ../../Img-2.0.1/png\png.c:562
#3 0x0000000000000000 in ?? ()
Checking out current tkimg svn source and building with:
$ configure --with-tcl=/clang64/lib --with-tk=/clang64/lib
$ make
then executing under gdb:
$ gdb --args wish stack.tcl
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ffee7f26f3f in png_free () from C:\apps\msys64\clang64\lib\Img2.1.0\pngtcl1648.dll
(gdb) bt
#0 0x00007ffee7f26f3f in png_free () from C:\apps\msys64\clang64\lib\Img2.1.0\pngtcl1648.dll
#1 0x00007ffee7f24dd6 in png_destroy_gamma_table ()
from C:\apps\msys64\clang64\lib\Img2.1.0\pngtcl1648.dll
#2 0x00007ffee7f298c7 in png_destroy_read_struct ()
from C:\apps\msys64\clang64\lib\Img2.1.0\pngtcl1648.dll
#3 0x0000000000000000 in ?? ()
Please note the botched stack trace, which may indicate that the stack is corrupted.
Please let me know if you need more information. Thanks.
I do not have MSYS2/Clang available, but running tests on Debian using similar compiler options (-fsanitize=address,undefined -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector-strong -mshstk) on current trunk did not show any stack corruptions.
Looking at the source of png.c, your first stack trace, where png_ptr is 0x0 in CommonMatch should not be possible, because png_ptr is checked just before calling CommonMatch.
I tested with Tcl/Tk 9.0.1. Which version of Tcl/Tk are you using?
Are you loading any other extensions, which may cause the stack corruption?
I'm using tcl/tk 8.6.16. There are no other extensions loaded, just the code above executed with wish.
I tried to replicate the problem in Linux, to no avail, even with Valgrind, but please note that Windows and Linux have different ABIs and different C runtimes. It is interesting that the crash does not happen with the MinGW64 environment (which uses the old MSCVCRT runtime).
All packages in MSYS2 (a few thousands of them) are built with -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector-strong and AFAIK this is the first time someone reports an stack smashing crash.
As soon as I have time I'll investigate the problem by placing breakpoints on those functions and watching what happens before the crash.
Thanks for your interest.
This looks like Tk is trying to load the jpg file as if it were a png, isn't it?
Then it reaches the LONGJMP and the stack is corrupted:
I'm not much of a C programmer (C++, yes) so my knowledge of setjmp/longjmp is almost none, never used it. Does the above ring any bells?
Looking at the build output, I see lots of warnings like this:
BTW, the code I'm running under gdb is a svn checkout of tkimg configured with "-O0 -g", no extra options. A sample compiler invocation:
(Please note that in the MSYS2 Clang64 environment
gccis an alias forclang)Changing
base/tkimg.hto use plainsetjmp/longjmpinstead of the__builtinvariants removes the crash, as well as the warnings. I'll ask some people about what's going on and come back with a patch. Thank you.Last edit: ofv 2025-06-07
We fixed the problem by applying the patch below. It also modifies
tif_ojpeg.cfor consistency.Do you remember why mingw32 was changed to use
__builtin_setjmp/__builtin_longjmp?The commit message from 2023-04-23 says:
For a discussion of the error see ex. [https://stackoverflow.com/questions/53709069/setjmp-longjmp-in-x86-64-w64-mingw32]
I don't know, which gcc versions are affected by the error.
If only "old" compilers are affected (ex. gcc 4.x), a more clean and simple solution would be:
Another advantage of this change would be, that we do not need to change the libtiff source code.
I have several MinGW gcc versions ranging from 4.9.2 to 14.2 available and
could check the next days, what versions are affected.
How does Clang report it's version number?
Thanks for the reference.
So GNUC < 5 alone will not cut it. Besides, we don't know for sure if recent gcc is fixed.
To be fair, my patch assumes that gcc with the Universal C Runtime will work. I didn't verify that. Both the patched and unpatched tkImg 2.0.1, built with gcc/UCRT do not crash.
Maybe the less risky thing is
?
I used the following script and attached (incorrect) TIFF file for testing.
Note, that the TIFF file is marked as suspicious (TIFF.CVE-2017-3042) by the
TACHYON virus scanner on VirusTotal.
Tested the following MinGW/gcc versions:
All of these crash when compiled with SETJMP/LONGJMP set to setjmp/longjmp.
When using the __builtin* versions, correct error messages like shown below are issued:
Gimp for example also issues the "Not a JPEG file" message.
Could you try the script and see, if it works for you.
Tested with unpatched 2.0.1 on mingw64 (gcc/msvcrt), ucrt64 (gcc/ucrt), clang64 (clang/ucrt), plus patched 2.0.1 (clang/ucrt).
Same output as yours on all cases.
Checked in tkimg.h with proposed change:
#if defined(__MINGW32__) && !defined(__aarch64__) && !defined(__clang__)Works for all of my test systems.
For the record, the commit in Mingw-packages is cf52b888301d4e0f66cf5116b0d9f4955876cb54
link to commit in github
That commit included the proposed change to tif_ojpeg.c, which I reckon it is unnecessary.
Thank you.
Fix included in new version 2.1.0.