Tk Source Code

View Ticket
Login
Ticket UUID: 56d4d132fd073245b64000b5f3e66c85c19d01f7
Title: Unsafe child interpreters cannot find Tk if wish is statically linked
Type: Bug Version: 9.1b1
Submitter: kjnash Created on: 2026-09-22 14:50:25
Subsystem: 84. Unix Build Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2026-10-30 15:53:07
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2026-10-30 15:53:07
Description:
(This bug applies to all builds, Windows and macOS as well as Unix.)

1. When wish is statically linked and has its tcl_library and
   tk_library in //zipfs:/, the following script fails:

    % interp create foo
    % foo eval package require tk

The problem is that pkgIndex.tcl for tk has not been installed.
The file is unnecessary for the main interpreter and for safe child
interpreters, but unsafe child interpreters cannot locate tk without
it.

The remedy is to install //zipfs:/app/tk_library/pkgIndex.tcl with
contents:

    if {![package vsatisfies [package provide Tcl] 9.0]} return
    package ifneeded tk 9.1b1 [list load {} Tk]
    package ifneeded Tk 9.1b1 [list package require -exact tk 9.1b1]

2. When wish is statically linked but has its tcl_library and
   tk_library in lib/, the same script fails.

In this case, lib/tk9.1/pkgIndex.tcl either does not exist, or refers
incorrectly to the dynamic Tk library, not the static one.

The remedy is to write or overwrite file lib/tk9.1/pkgIndex.tcl with
the same contents as above.

The bug afflicts both Tk 9.0 and 9.1. A fix for 9.1 will be provided
shortly in a fossil branch named after this bug.

3. A regression test

A test is provided in a new file tests/interpTk.test.  The test has a
constraint "useInstalledWish" because, at present, it is necessary to
run the test from the Tcl/Tk installation, not from "make test".

Currently, tests run with "make test" use a binary tktest(.exe) that
uses the library/ from the Tk source rather than the lib/tk9.1/ or
//zipfs:/ that belong to a Tk installation.  However, the purpose of
the new test is to ensure that pkgIndex.tcl is in the correct location
and has the correct contents. For this, tktest(.exe) with the source
library/ is unsuitable, and the test is valid only if it is run from
the installed wish((s).exe), e.g.

    path1/to/wish  path2/to/tests/all.tcl  -verbose bps \
            -file interpTk.test  -constraints useInstalledWish
User Comments: jan.nijtmans added on 2026-10-30 15:53:07:

👍


dgp added on 2026-10-30 15:38:39:
All better on the branch tips

jan.nijtmans added on 2026-10-30 15:31:33:

@kjnash: Sorry it took so much time to have a look at it. This definitely should be in Tk 8.0.5


jan.nijtmans added on 2026-10-30 15:27:31:

Got .... missing '$'. Don't know how that happened :-(

Should be corrected now.


dgp added on 2026-10-30 15:11:37:
Here is the failing compile line.  Some of it just looks wrong.

gcc -c -I/home/dgp/fossil/tk9.0/unix/../unix -I/home/dgp/fossil/tk9.0/unix/../generic -I/home/dgp/fossil/tk9.0/unix/../bitmaps {X11_INCLUDES} -O2  -pipe -finput-charset=UTF-8  -Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -Wc++-compat -fextended-identifiers {SHLIB_CFLAGS} -I/home/dgp/fossil/tcl9.0/generic -I/home/dgp/fossil/tcl9.0/unix -DPACKAGE_NAME=\"tk\" -DPACKAGE_TARNAME=\"tk\" -DPACKAGE_VERSION=\"9.0\" -DPACKAGE_STRING=\"tk\ 9.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DTCL_CFGVAL_ENCODING=\"utf-8\" -DSTATIC_BUILD=1 -DHAVE_STDIO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_TIME_H=1 -DSTDC_HEADERS=1 -DMODULE_SCOPE=extern\ __attribute__\(\(__visibility__\(\"hidden\"\)\)\) -DHAVE_HIDDEN=1 -DHAVE_CAST_TO_UNION=1 -DHAVE_VFORK=1 -DHAVE_POSIX_SPAWNP=1 -DHAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2=1 -DHAVE_POSIX_SPAWNATTR_SETFLAGS=1 -DTCL_SHLIB_EXT=\".so\" -DNDEBUG=1 -DTCL_CFG_OPTIMIZED=1 -D_LARGEFILE64_SOURCE=1 -DTCL_WIDE_INT_IS_LONG=1 -DHAVE_INTPTR_T=1 -DHAVE_UINTPTR_T=1 -DHAVE_PW_GECOS=1 -DHAVE_LIBXFT=1 -DHAVE_XFT=1 -DHAVE_XSS=1 -DZIPFS_BUILD=2 {PROTO_FLAGS}    {NO_DEPRECATED_FLAGS}   -fno-lto /home/dgp/fossil/tk9.0/unix/../generic/tkStubLib.c

dgp added on 2026-10-30 15:09:38:
The commit to the 9.0 branch [19723732ec] breaks my --disable-shared
build on an Ubuntu Linux system.  The failure shows up attempting
to compile tkStubLib.c

gcc: warning: {X11_INCLUDES}: linker input file unused because linking not done
gcc: error: {X11_INCLUDES}: linker input file not found: No such file or directory
gcc: warning: {SHLIB_CFLAGS}: linker input file unused because linking not done
gcc: error: {SHLIB_CFLAGS}: linker input file not found: No such file or directory
gcc: warning: {PROTO_FLAGS}: linker input file unused because linking not done
gcc: error: {PROTO_FLAGS}: linker input file not found: No such file or directory
gcc: warning: {NO_DEPRECATED_FLAGS}: linker input file unused because linking not done
gcc: error: {NO_DEPRECATED_FLAGS}: linker input file not found: No such file or directory

kjnash added on 2026-09-28 18:11:49:
Should I commit this to 9.1.0?

kjnash added on 2026-09-28 10:32:50:
Thanks, I have now edited tests/constraints.tcl to use this form.

serhiy.storchaka added on 2026-09-28 06:47:09:

Thank you, Keith. The command line options are processed before tests/constraints.tcl is sourced, so the constraint can be set from them, and the tests still run only on request:

testConstraint useInstalledWish [expr {
    "useInstalledWish" in [tcltest::configure -constraints]
}]

With it the tests are skipped by default and run with -constraints useInstalledWish.


kjnash added on 2026-09-28 03:54:16:
Hi Serhiy and Andreas,

Thanks for your review, I agree with all your suggestions, and I have
implemented them with one further change.

It appears that the settings in tests/constraints.tcl cannot be
overridden by a -constraints option in the "test" command.  So setting
  testConstraint useInstalledWish 0
appears to mean that tests with this constraint will not be executed
even if "-constraints useInstalledWish" is specified on the command
line.  So in tests/constraints.tcl I have instead set

testConstraint useInstalledWish [expr {
    (![string match tktest* [file tail [info nameofexecutable]]])
}]

so that the tests will run if wish is used instead of the tktest executable.

I hope the branch will now be suitable for merging into the trunk.

Best wishes,

Keith.

serhiy.storchaka added on 2026-09-23 10:43:41:

I looked at branch bug-56d4d132fd-child-interp ([db2fc66a5f]). The approach looks right to me, two remarks:

  • tests/interpTk.test hard-codes -result 9.1b1, which breaks at the next version bump — $::tk_patchLevel would do. And the constraint useInstalledWish is not defined in tests/constraints.tcl, so the file is silently skipped in every normal run; testConstraint useInstalledWish 0 there would at least make the skip visible.
  • win/Makefile.in detects a static build as ${EXESUFFIX} = "s.exe". That is true today, but SHARED_BUILD is already defined in the same file (line 234), and unix/Makefile.in in this very patch uses TK_SHARED_BUILD.


kjnash added on 2026-09-22 23:57:57:
The exhaustive builds and tests of pkgIndex.tcl were done on Tk 9.1b1rc2,
checkin [68ce4fa33f]. The relevant files

  unix/Makefile.in
  win/Makefile.in
  win/makefile.vc

have not changed in the trunk since then.

kjnash added on 2026-09-22 23:20:18:
The fix is in branch [bug-56d4d132fd-child-interp].

Please could you review this branch for merging into the trunk.

The branch adds a test file tests/interpTk.test, and patches the files

  unix/Makefile.in
  win/Makefile.in
  win/makefile.vc

The patches are limited to the build procedure, and concern the existence,
location, and contents of pkgIndex.tcl.

Tcl/Tk was built and installed, with and without the patch, for cases
 --disable-zipfs  | --enable-zipfs
 --disable-shared | --enable-shared
(i.e. 8 builds per platform).

Each build was successful and produced a functioning wish(s(.exe)).
The builds with the patch were examined for the existence, location, and
contents of pkgIndex.tcl; and were tested with tests/interpTk.test.  The
results were as intended.

These builds used an earlier version of Tk from the trunk, and were
performed for Linux x86_64, macOS x86_64, Windows/MSYS+gcc, and Windows/VC++
- i.e. 32 builds altogether.

Less exhaustive tests were made after committing [db2fc66a], and were
consistent with the above.  I had hoped to compare the results of the full
suite of Tk tests, but unfortunately these are not consistent from run to
run on the same build.