Skip to content
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

Add nip4 #72

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Add nip4 #72

wants to merge 12 commits into from

Conversation

jcupitt
Copy link
Member

@jcupitt jcupitt commented Feb 16, 2025

First attempt at a win32 build for nip4.

This should probably stay in a branch for now!

nip4 needs xml output, so I also added --with-output to libxml2. I don't know how much this will increase the size of libvips builds. Perhaps this should only be enabled for nip4.

We now have two copies of eg. gtk.mk. This should maybe be moved out of plugins/.

Packaging could be improved -- we don't need to include eg. vips.exe, include/ etc.

@jcupitt jcupitt marked this pull request as draft February 16, 2025 16:37
@jcupitt
Copy link
Member Author

jcupitt commented Feb 16, 2025

nip4 builds successfully. I've not tried running the thing yet.

@kleisauke
Copy link
Member

Great! I'll run a test on my Windows workstation later.

nip4 needs xml output, so I also added --with-output to libxml2. I don't know how much this will increase the size of libvips builds. Perhaps this should only be enabled for nip4.

We now have two copies of eg. gtk.mk. This should maybe be moved out of plugins/.

I addressed both issues with commit af5c2e1.

Mingw-w64 in UCRT mode supports C99 `vsnprintf()`, `snprintf()` and
`printf()` well enough. Avoids pulling in gnulib compat functions.
@kleisauke
Copy link
Member

kleisauke commented Feb 17, 2025

Commit eb094a1 fixes a segv in _g_gnulib_vsnprintf on startup (and also ensures GLIB_USING_SYSTEM_PRINTF is defined in glibconfig.h). I now see:

Details

screenshot-1
screenshot-2

@jcupitt
Copy link
Member Author

jcupitt commented Feb 17, 2025

Hurrah!

Can you drag in an image file from explorer (the file manager)?

@kleisauke
Copy link
Member

Dragging an image from the file explorer appears to work fine!

However, the logo2.ws and framing.ws workspaces from share/nip4/data/examples seem to cause a crash, while the others function without any issues based on a quick test.

Additionally, the new tab icon appears to be missing (see the screenshot above). We should likely rely on the Adwaita icon theme for this (see PR jcupitt/vipsdisp#24 for context).

(I still want to investigate the root cause of that _g_gnulib_vsnprintf crash, as it could lead to issues when compiling with MSVC - https://github.com/GNOME/glib/blob/2.83.3/meson.build#L1194-L1203)

@jcupitt
Copy link
Member Author

jcupitt commented Feb 18, 2025

framing.ws won't work, but logo2.ws works on linux. It might be some font rendering issue.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 18, 2025

Oooo, something else to test ... can you open an image view window, ^C, then ^V in mspaint? It might work in the other direction too. Or it might not :(

@jcupitt
Copy link
Member Author

jcupitt commented Feb 18, 2025

(I'm on a laptop right now with no easy way to test on windows. I'll be back at my desk on Thursday)

@kleisauke
Copy link
Member

I still want to investigate the root cause of that _g_gnulib_vsnprintf crash

AddressSanitizer reports this as:

Details
$ ./nip4.exe
=================================================================
==38412==ERROR: AddressSanitizer: access-violation on unknown address 0x00129f50024f (pc 0x7ffb334bc151 bp 0x00129f4fceb0 sp 0x00129f4fce40 T0)
==38412==The signal is caused by a WRITE memory access.
    #0 0x7ffb334bc150 in _g_gnulib_vsnprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gnulib/printf.c:128:21
    #1 0x7ffb334a86c8 in g_vsnprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gprintf.c:295:10
    #2 0x7ffb334a86c8 in g_snprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gprintf.c:173:12
    #3 0x7ff6b7d67e9d in nativeize_path /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1364:3
    #4 0x7ff6b7d67e9d in calli_string_filename /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1568:2
    #5 0x7ff6b7d683af in calli_string_filenameva /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1582:9
    #6 0x7ff6b7d683af in existsf /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1641:8
    #7 0x7ff6b7d6b081 in get_savedir /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:2503:29
    #8 0x7ff6b7d00afd in main /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/main.c:395:27
    #9 0x7ff6b7c6133b in __tmainCRTStartup /data/mxe/tmp-llvm-mingw-x86_64-w64-mingw32.shared.gtk4.debug.all/mstorsjo-llvm-mingw-73e3131.build_/mingw-w64-mingw-w64-993da58/mingw-w64-crt/crt/crtexe.c:266:15
    #10 0x7ff6b7c61175 in .l_startw /data/mxe/tmp-llvm-mingw-x86_64-w64-mingw32.shared.gtk4.debug.all/mstorsjo-llvm-mingw-73e3131.build_/mingw-w64-mingw-w64-993da58/mingw-w64-crt/crt/crtexe.c:155:9
    #11 0x7ffbbb8ae8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #12 0x7ffbbcefbf2b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800bbf2b)

==38412==Register values:
rax = 0  rbx = 129f4fce80  rcx = 129f4ff250  rdx = 118a18ba3010
rdi = 253e9f9c8  rsi = 129f4fce40  rbp = 129f4fceb0  rsp = 129f4fce40
r8  = 23  r9  = 40  r10 = 7ffbba8a0000  r11 = 7ffbba98dfd1
r12 = 118a18ba3010  r13 = 18218b80000  r14 = 0  r15 = 129f50024f
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: access-violation /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gnulib/printf.c:128:21 in _g_gnulib_vsnprintf
==38412==ABORTING
$ ./nip4.exe
=================================================================
==40092==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00caa2afdb5f at pc 0x7ffb334bc1cb bp 0x00caa2afa820 sp 0x00caa2afa868
WRITE of size 1 at 0x00caa2afdb5f thread T0
    #0 0x7ffb334bc1ca in _g_gnulib_vsnprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gnulib/printf.c:128:21
    #1 0x7ffb334a86c8 in g_vsnprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gprintf.c:295:10
    #2 0x7ffb334a86c8 in g_snprintf /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gprintf.c:173:12
    #3 0x7ff6b7d67297 in nativeize_path /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1364:3
    #4 0x7ff6b7d67297 in is_absolute /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1771:2
    #5 0x7ff6b7d67edc in absoluteize_path /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1436:7
    #6 0x7ff6b7d67edc in calli_string_filename /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1569:2
    #7 0x7ff6b7d683af in calli_string_filenameva /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1582:9
    #8 0x7ff6b7d683af in existsf /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1641:8
    #9 0x7ff6b7d6b081 in get_savedir /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:2503:29
    #10 0x7ff6b7d00afd in main /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/main.c:395:27
    #11 0x7ff6b7c6133b in __tmainCRTStartup /data/mxe/tmp-llvm-mingw-x86_64-w64-mingw32.shared.gtk4.debug.all/mstorsjo-llvm-mingw-73e3131.build_/mingw-w64-mingw-w64-993da58/mingw-w64-crt/crt/crtexe.c:266:15
    #12 0x7ff6b7c61175 in .l_startw /data/mxe/tmp-llvm-mingw-x86_64-w64-mingw32.shared.gtk4.debug.all/mstorsjo-llvm-mingw-73e3131.build_/mingw-w64-mingw-w64-993da58/mingw-w64-crt/crt/crtexe.c:155:9
    #13 0x7ffbbb8ae8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #14 0x7ffbbcefbf2b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800bbf2b)

Address 0x00caa2afdb5f is located in stack of thread T0 at offset 3551 in frame
    #0 0x7ff6b7d67bdf in calli_string_filename /var/tmp/tmp-nip4-x86_64-w64-mingw32.shared.gtk4.debug.all/nip4-9.0.0-10.build_/../nip4-9.0.0-10/src/util.c:1564

  This frame has 4 object(s):
    [32, 292) 'buf.i' (line 1437)
    [368, 4464) 'filename.i' (line 1351) <== Memory access at offset 3551 is inside this variable
    [4592, 8688) 'mode.i' (line 1352)
    [8816, 9076) 'buf' (line 1565)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp, SEH and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope /var/tmp/tmp-glib-x86_64-w64-mingw32.shared.gtk4.debug.all/glib-2.83.3.build_/../glib-2.83.3/glib/gnulib/printf.c:128:21 in _g_gnulib_vsnprintf
Shadow bytes around the buggy address:
  0x00caa2afd880: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afd900: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afd980: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afda00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afda80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
=>0x00caa2afdb00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8[f8]f8 f8 f8 f8
  0x00caa2afdb80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afdc00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afdc80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afdd00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x00caa2afdd80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
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
==40092==ABORTING

(I think the second report is a false positive as I was only able to reproduce this once)

Applying this substitution in src/util.c:

$ sed -i "s/VIPS_PATH_MAX/FILENAME_MAX/g" src/util.c

seems to resolve the issue! However, perhaps we need to standardize that to VIPS_PATH_MAX instead.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 18, 2025

Ah! I vaguely remember, is FILENAME_MAX only 256 on windows? I think that's why we added VIPS_PATH_MAX (to get something sensibly large on all platforms).

I'll switch nip4 to use VIPS_PATH_MAX everywhere.

I see there are quite a few FILENAME_MAX in libvips, maybe some of those should change too?

@kleisauke
Copy link
Member

I vaguely remember, is FILENAME_MAX only 256 on windows?

It seems it's only 260.

$ docker run --rm -v ${PWD}:/src -w /src -it mstorsjo/llvm-mingw:latest
root@c7af8b0e7b26:/src# echo -e '#include <stdio.h>\nint main(void){printf("%d\\n", FILENAME_MAX);return 0;}' | x86_64-w64-mingw32-clang -xc -otest.exe -
root@c7af8b0e7b26:/src# exit
$ ./test.exe
260

I'll switch nip4 to use VIPS_PATH_MAX everywhere.

Great!

I see there are quite a few FILENAME_MAX in libvips, maybe some of those should change too?

It's probably fine, except when mixed with VIPS_PATH_MAX. For example, calli_string_filename() passed char buf[FILENAME_MAX] to nativeize_path(), which was using VIPS_PATH_MAX as its buffer size.

By backporting a fix from GTK. However, it's likely to crash only if
GLib was built with `-Dglib_checks=false`.
@kleisauke
Copy link
Member

Commit 94ffed5 resolves a crash that occurred when opening logo2.ws.

can you open an image view window, ^C, then ^V in mspaint? It might work in the other direction too.

Works in both directions! 👍

@jcupitt
Copy link
Member Author

jcupitt commented Feb 19, 2025

Works in both directions! 👍

OMG!

How about PRT SCR, then ^V into an image window?

@kleisauke
Copy link
Member

How about PRT SCR, then ^V into an image window?

That works too! If you repeatedly take a screenshot of the current image window and paste it back in, you'll create a lovely Droste effect. :)

@jcupitt
Copy link
Member Author

jcupitt commented Feb 19, 2025

/me faints

@jcupitt jcupitt marked this pull request as ready for review February 24, 2025 17:24
@jcupitt
Copy link
Member Author

jcupitt commented Feb 24, 2025

I think this is done! I've made 9.0.1, a first public release, built it with this PR, and it seems fine (to me).

Though ^V of screenshots into image windows isn't working on my win10 install, strangely :( At least text rendering looks OK.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 24, 2025

Oh wait, plots are not working :( Histogram > New > Identity crashes instantly.

@kleisauke
Copy link
Member

I think this is done! I've made 9.0.1, a first public release, built it with this PR, and it seems fine (to me).

Great!

Though ^V of screenshots into image windows isn't working on my win10 install, strangely :(

Does pressing PrtScr copy the screenshot to the clipboard? If not, a third-party utility (possibly Dropbox) may be overriding the default print screen functionality.

Windows 10 also includes a snipping tool, which can be enabled using Windows logo key + Shift + S.

Oh wait, plots are not working :( Histogram > New > Identity crashes instantly.

I'll investigate this on my Windows 11 workstation.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

I'm poking about in VS now, it's crashing in kplot realloc for some reason. I just need to get VS to load symbols correctly argh ...

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

It looks like kplot is missing symbols, and it's failing to load source for other parts of nip4 because of path differences.

Maybe realloc(0) isn't allowed on win? Or maybe kplot is linking to a different malloc?

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

Neither change seemed to fix it :( Though I didn't try both together. I think I'd need a working debugger to investigate more.

@kleisauke
Copy link
Member

It looks like kplot is missing symbols, and it's failing to load source for other parts of nip4 because of path differences.

Oh huh, I see this in WinDbg (with the associated PDBs loaded in):

nip4!reallocarray+0x1
nip4!kplotdat_attach+0x31
nip4!kplot_attach_data+0x4a
nip4!drawstate_build_kplot+0xcf
nip4!plotdisplay_set_property+0xb3
libgobject_2_0_0!object_set_property+0x9f
libgobject_2_0_0!g_object_set_valist+0x1de
libgobject_2_0_0!g_object_set+0x1d
nip4!plotview_refresh+0x120
nip4!vobject_refresh_timeout_cb+0x43
libglib_2_0_0!g_timeout_dispatch+0x43
libglib_2_0_0!g_main_context_dispatch_unlocked+0xef
libglib_2_0_0!g_main_context_iterate_unlocked+0x32f
libglib_2_0_0!g_main_context_iteration+0x35
libgio_2_0_0!g_application_run+0x17a
nip4!main+0x602

Perhaps kplot needs to be linked with link_whole in nip4? That is what we do in libvips with libvips_components.

Maybe realloc(0) isn't allowed on win? Or maybe kplot is linking to a different malloc?

realloc(ptr, 0) and/or realloc(0, size) is likely UB or may trigger a UCRT security feature (Universal C Runtime in Windows). I'll try to link against the debug version of the UCRT to see if it provides more insight.

@kleisauke
Copy link
Member

Regarding the print screen issue, it looks like that pressing PrtScr in Windows captures a BMP image by default, which cannot be pasted into the image window (GTK inspector shows: "Cannot get clipboard data. No compatible transfer format found."). However, Windows 11 defaults to the snipping tool, which places a proper PNG image in the clipboard.

As a workaround in Windows 10, you can use Windows logo key + Shift + S to capture an image in PNG format.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

As a workaround in Windows 10, you can use Windows logo key + Shift + S to capture an image in PNG format.

Ah, nice!

@kleisauke
Copy link
Member

realloc(ptr, 0) and/or realloc(0, size) is likely UB or may trigger a UCRT security feature (Universal C Runtime in Windows).

Actually, both seems to be fine according to this gist: https://gist.github.com/kleisauke/91bca78ba192d68999e08f03eb4ec560.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

I pushed a thing to nip4 master to build kplot directly as part of nip4 build:

jcupitt/nip4@499da60

I think it's probably not a linking issue either.

I've not tried getting kplot to use malloc/free (or g_malloc()/g_free()?) rather than realloc.

I tried running under valgrind on linux and couldn't see any heap corruption, so I don't think that's it.

@kleisauke
Copy link
Member

I found a fix, working on a PR now.

@kleisauke
Copy link
Member

PR jcupitt/nip4#1 should fix this.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

Woah! you are amazing! Thank you very much Kleis.

@jcupitt
Copy link
Member Author

jcupitt commented Feb 25, 2025

We have a first public release. I'll ask users to begin testing.

https://github.com/jcupitt/nip4/releases/tag/v9.0.1-3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants