-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows: Experiencing silent crash when attempting to convert a JPEG to a GIF #4125
Comments
I'm unable to reproduce this locally.
On Windows this exit code often indicates some kind of file permission problem e.g. input file owned by admin user but process run as non-admin. |
Interesting, I wasn't having the same issue with PNG or TIFF formats, but is consistent with GIF. I'll try another PC and see what happens, thanks for the quick response. |
I see the same behavior on a Windows 10 machine:
I tried running the reproducer in an Administrator Command prompt to see if the behavior was any different but saw the same results. The files are all created by and owned by the same user. Any tips for debugging further? |
Worth noting, just tried with a newer node (v20.14.0) and receive a Segmentation Fault message printed to stderr (I see no message with v18) and an exit code of 139 |
Thanks for the extra info, I'll try on another machine later. Are you able to get a backtrace of the crash? The PDB symbol files for libvips v8.15.2 and its dependencies (as provided by sharp v0.33.4) are available at https://s3.eu-west-1.amazonaws.com/libvips-packaging/pdb/8.15.2/vips-pdb-w64-web-8.15.2-static.zip
My current thinking is that this relates to palette generation/mapping, as used for GIF output. Are you able to create a palette-based PNG via |
@lovell I am able to invoke
Here's a more detailed version as well:
|
Thank you, this is very helpful, and suggests the crash might be from within the LZW compression logic of the cgif dependency. The segfault appears to occur in one of the two calls to I assume this code is attempting to write beyond the end of https://github.com/dloebl/cgif/blob/43976ce4ace9ad60ba3cf7cf5aaabc2d480170f9/src/cgif_raw.c#L327 I'll keep investigating. |
I was able to reproduce this issue on Windows using: $ vips copy 337010030-e9a3fdbf-b30f-4b60-8e73-9f98a5446695.jpg x.gif
$ echo %errorlevel%
-1073741819 However, I was unable to reproduce the issue on Linux, even when running with ASan/UBSan sanitizers: $ python infra/helper.py reproduce libvips gifsave_buffer_fuzzer ~/Downloads/337010030-e9a3fdbf-b30f-4b60-8e73-9f98a5446695.jpg (with this check removed) I thought this might be a security feature of UCRT (Universal C Runtime in Windows), but linking against the debug version of the UCRT did not provide any additional information. I'll try to build the binaries with ASan/UBSan on Windows, hopefully that will provide extra information. |
AddressSanitizer reports it as heap-buffer-overflow: Details$ set ASAN_SYMBOLIZER_PATH=C:\llvm-mingw-20240606-ucrt-x86_64\bin\llvm-symbolizer.exe
$ vips copy 337010030-e9a3fdbf-b30f-4b60-8e73-9f98a5446695.jpg x.gif
=================================================================
==121936==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x012989bf6c41 at pc 0x7ff80e71811c bp 0x000c54ef90b0 sp 0x000c54ef90f8
WRITE of size 255 at 0x012989bf6c41 thread T0
#0 0x7ff80e71811b in __asan_memcpy /var/tmp/tmp-compiler-rt-sanitizers-x86_64-w64-mingw32.static.debug.web/llvm-project-18.1.7.src/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:63:3
#1 0x7fffbb5ea305 in create_byte_list_block /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:287:5
#2 0x7fffbb5ea305 in LZW_GenerateStream /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:331:19
#3 0x7fffbb5e85a0 in cgif_raw_addframe /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:559:9
#4 0x7fffbb11f6c0 in flushFrame /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif.c:340:7
#5 0x7fffbb11fcd5 in cgif_close /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif.c:488:11
#6 0x7fffbab10b79 in vips_foreign_save_cgif_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/foreign/cgifsave.c:873:2
#7 0x7fffbab136aa in vips_foreign_save_cgif_target_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/foreign/cgifsave.c:1007:6
#8 0x7fffbaee2df1 in vips_object_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:372:6
#9 0x7fffbaf00ab2 in vips_cache_operation_buildp /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/cache.c:834:7
#10 0x7fffbaf1188e in vips_call_required_optional /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:977:6
#11 0x7fffbaf13067 in vips_call_by_name /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1017:11
#12 0x7fffbaf1331a in vips_call_split_option_string /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1138:11
#13 0x7fffbaef3c8d in vips_image_write_to_file /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/image.c:2704:12
#14 0x7fffbaee8389 in vips_object_get_argument_to_string /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:2243:8
#15 0x7fffbaf13ded in vips_call_argv_output /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1420:8
#16 0x7fffbaee3217 in vips_argument_map /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:612:17
#17 0x7fffbaf1391d in vips_call_argv /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1487:6
#18 0x7ff7ff901a68 in main /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/tools/vips.c:884:7
#19 0x7ff7ff901310 in __tmainCRTStartup /var/tmp/tmp-llvm-mingw-x86_64-w64-mingw32.static.debug.web/mstorsjo-llvm-mingw-ab7e195.build_/mingw-w64-mingw-w64-f97814b/mingw-w64-crt/crt/crtexe.c:267:15
#20 0x7ff7ff901365 in .l_start /var/tmp/tmp-llvm-mingw-x86_64-w64-mingw32.static.debug.web/mstorsjo-llvm-mingw-ab7e195.build_/mingw-w64-mingw-w64-f97814b/mingw-w64-crt/crt/crtexe.c:188:9
#21 0x7ff88389257c (C:\WINDOWS\System32\KERNEL32.DLL+0x18001257c)
#22 0x7ff884dcaf27 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18005af27)
0x012989bf6c41 is located 0 bytes after 676929-byte region [0x012989b51800,0x012989bf6c41)
allocated by thread T0 here:
#0 0x7ff80e719641 in malloc /var/tmp/tmp-compiler-rt-sanitizers-x86_64-w64-mingw32.static.debug.web/llvm-project-18.1.7.src/compiler-rt/lib/asan/asan_malloc_win.cpp:98:3
#1 0x7fffbb5e9ef1 in LZW_GenerateStream /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:329:19
#2 0x7fffbb5e85a0 in cgif_raw_addframe /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:559:9
#3 0x7fffbb11f6c0 in flushFrame /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif.c:340:7
#4 0x7fffbb11fcd5 in cgif_close /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif.c:488:11
#5 0x7fffbab10b79 in vips_foreign_save_cgif_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/foreign/cgifsave.c:873:2
#6 0x7fffbab136aa in vips_foreign_save_cgif_target_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/foreign/cgifsave.c:1007:6
#7 0x7fffbaee2df1 in vips_object_build /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:372:6
#8 0x7fffbaf00ab2 in vips_cache_operation_buildp /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/cache.c:834:7
#9 0x7fffbaf1188e in vips_call_required_optional /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:977:6
#10 0x7fffbaf13067 in vips_call_by_name /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1017:11
#11 0x7fffbaf1331a in vips_call_split_option_string /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1138:11
#12 0x7fffbaef3c8d in vips_image_write_to_file /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/image.c:2704:12
#13 0x7fffbaee8389 in vips_object_get_argument_to_string /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:2243:8
#14 0x7fffbaf13ded in vips_call_argv_output /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1420:8
#15 0x7fffbaee3217 in vips_argument_map /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/object.c:612:17
#16 0x7fffbaf1391d in vips_call_argv /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/libvips/iofuncs/operation.c:1487:6
#17 0x7ff7ff901a68 in main /var/tmp/tmp-vips-web-x86_64-w64-mingw32.static.debug.web/vips-8.15.2.build_/../vips-8.15.2/tools/vips.c:884:7
#18 0x7ff7ff901310 in __tmainCRTStartup /var/tmp/tmp-llvm-mingw-x86_64-w64-mingw32.static.debug.web/mstorsjo-llvm-mingw-ab7e195.build_/mingw-w64-mingw-w64-f97814b/mingw-w64-crt/crt/crtexe.c:267:15
#19 0x7ff7ff901365 in .l_start /var/tmp/tmp-llvm-mingw-x86_64-w64-mingw32.static.debug.web/mstorsjo-llvm-mingw-ab7e195.build_/mingw-w64-mingw-w64-f97814b/mingw-w64-crt/crt/crtexe.c:188:9
#20 0x7ff88389257c (C:\WINDOWS\System32\KERNEL32.DLL+0x18001257c)
#21 0x7ff884dcaf27 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18005af27)
SUMMARY: AddressSanitizer: heap-buffer-overflow /var/tmp/tmp-cgif-x86_64-w64-mingw32.static.debug.web/cgif-0.4.0.build_/../cgif-0.4.0/src/cgif_raw.c:287:5 in create_byte_list_block
Shadow bytes around the buggy address:
0x012989bf6980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x012989bf6a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x012989bf6a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x012989bf6b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x012989bf6b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x012989bf6c00: 00 00 00 00 00 00 00 00[01]fa fa fa fa fa fa fa
0x012989bf6c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x012989bf6d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x012989bf6d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x012989bf6e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x012989bf6e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==121936==ABORTING |
@dloebl Daniel, you may be interested in this discussion. |
Thanks for letting me know, @lovell! It's strange that this issue only shows up on Windows. I'll take a look today |
I may have found the culprit. It appears that the For example, consider the following test program: #include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#define MAX_CODE_LEN 12
#define BLOCK_SIZE 0xFF
int main() {
uint32_t lzwPos = 1847622;
uint64_t MaxByteListLen = MAX_CODE_LEN*lzwPos/8ul +2ul +1ul;
uint64_t MaxByteListBlockLen = MAX_CODE_LEN*lzwPos*(BLOCK_SIZE+1ul)/8ul/BLOCK_SIZE +2ul +1ul +1ul;
printf("MaxByteListLen: %" PRIu64 "\n", MaxByteListLen);
printf("MaxByteListBlockLen: %" PRIu64 "\n", MaxByteListBlockLen);
return 0;
} When run on Fedora: $ docker run --rm -v ${PWD}:/src -w /src -it fedora:40 sh -c "dnf install -y gcc && gcc test-cgif.c && ./a.out"
MaxByteListLen: 2771436
MaxByteListBlockLen: 2782305 And on Windows: $ docker run --rm -v ${PWD}:/src -w /src -it mstorsjo/llvm-mingw:latest x86_64-w64-mingw32-clang test-cgif.c -o test.exe
$ ./test.exe
MaxByteListLen: 2771436
MaxByteListBlockLen: 676929 By changing the constants to @@ -7,8 +7,8 @@
int main() {
uint32_t lzwPos = 1847622;
- uint64_t MaxByteListLen = MAX_CODE_LEN*lzwPos/8ul +2ul +1ul;
- uint64_t MaxByteListBlockLen = MAX_CODE_LEN*lzwPos*(BLOCK_SIZE+1ul)/8ul/BLOCK_SIZE +2ul +1ul +1ul;
+ uint64_t MaxByteListLen = MAX_CODE_LEN*lzwPos/8ull +2ull +1ull;
+ uint64_t MaxByteListBlockLen = MAX_CODE_LEN*lzwPos*(BLOCK_SIZE+1ull)/8ull/BLOCK_SIZE +2ull +1ull +1ull;
printf("MaxByteListLen: %" PRIu64 "\n", MaxByteListLen);
printf("MaxByteListBlockLen: %" PRIu64 "\n", MaxByteListBlockLen); The output for |
PR dloebl/cgif#70 should fix this. As an aside, this also affects the WebAssembly builds. For example, running the sample in this playground link results in a crash with the error message: |
I've just tagged a new release (v0.4.1) that should fix this issue: https://github.com/dloebl/cgif/releases/tag/v0.4.1 |
Thank you @kleisauke for investigating this and thank you @dloebl for fixing cgif. cgif v0.4.1 will hopefully be included in sharp as part of the next release, v0.33.5. |
v0.33.5 now available with an updated cgif. |
Possible bug
Is this a possible bug in a feature of sharp, unrelated to installation?
npm install sharp
completes without error.node -e "require('sharp')"
completes without error.If you cannot confirm both of these, please open an installation issue instead.
Are you using the latest version of sharp?
sharp
as reported bynpm view sharp dist-tags.latest
.If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.
If you are using another package which depends on a version of
sharp
that is not the latest, please open an issue against that package instead.What is the output of running
npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp
?Does this problem relate to file caching?
The default behaviour of libvips is to cache input files, which can lead to
EBUSY
orEPERM
errors on Windows.Use
sharp.cache(false)
to switch this feature off.sharp.cache(false)
does not fix this problem.Does this problem relate to images appearing to have been rotated by 90 degrees?
Images that contain EXIF Orientation metadata are not auto-oriented. By default, EXIF metadata is removed.
To auto-orient pixel values use the parameter-less
rotate()
operation.To retain EXIF Orientation use
keepExif()
.Using
rotate()
orkeepExif()
does not fix this problem.What are the steps to reproduce?
Using the reproducer, attempt to convert the attached JPEG image, into a GIF.
What is the expected behaviour?
The JPEG input image is converted into a GIF image or an error is returned in the
catch()
handler.Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem
Running the following script as:
node ./index.js 1.jpg
Where
1.jpg
is the attached image will cause node to crash and return with an exit code of5
The file
converted.gif
will be created but contains 0 bytes.Neither the
then()
orcatch()
handlers are invoked.Please provide sample image(s) that help explain this problem
The text was updated successfully, but these errors were encountered: