From 31020bf9636cfa2291eb4c13ce9707d6a844f96d Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 28 Jul 2026 11:01:33 +0900 Subject: [PATCH] win32: handle quoted LIBRARY names in def files Parse quoted LIBRARY names as a single token and add the default .dll extension when needed. Allocate the stored name dynamically. Add a Windows regression test using a quoted name with spaces. --- tccpe.c | 27 +++++++++++++++++++++++++-- tests/tests2/147_def_library.c | 21 +++++++++++++++++++++ tests/tests2/147_def_library.def.in | 3 +++ tests/tests2/147_def_library.expect | 1 + tests/tests2/Makefile | 13 ++++++++++++- 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 tests/tests2/147_def_library.c create mode 100644 tests/tests2/147_def_library.def.in create mode 100644 tests/tests2/147_def_library.expect diff --git a/tccpe.c b/tccpe.c index c076d084..ab30268e 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1775,10 +1775,26 @@ static char *get_token(char **s, char *f) return p; } +/* Read a LIBRARY argument whose quotes may protect whitespace. */ +static char *get_libname(char **s, char *f) +{ + char *p = trimfront(*s), *e; + if (*p != '"') + return get_token(s, f); + for (e = ++p; *e && *e != '"' && *e != '\r' && *e != '\n'; ++e) + ; + if (*e != '"' || (unsigned char)e[1] > ' ') + return NULL; + *s = trimfront(e + 1); + *f = **s; + *e = 0; + return p; +} + static int pe_load_def(TCCState *s1, int fd) { int state = 0, ret = -1, dllindex = 0, ord; - char dllname[80], *buf, *line, *p, *x, next; + char *dllname = NULL, *buf, *line, *p, *x, next; buf = tcc_load_text(fd); if (!buf) @@ -1792,7 +1808,13 @@ static int pe_load_def(TCCState *s1, int fd) case 0: if (0 != stricmp(p, "LIBRARY") || next == '\n') goto quit; - pstrcpy(dllname, sizeof dllname, get_token(&line, &next)); + p = get_libname(&line, &next); + if (!p || !*p) + goto quit; + dllname = tcc_malloc(strlen(p) + 5); + strcpy(dllname, p); + if (!*tcc_fileextension(dllname)) + strcat(dllname, ".dll"); ++state; break; case 1: @@ -1823,6 +1845,7 @@ skip: } ret = 0; quit: + tcc_free(dllname); tcc_free(buf); return ret; } diff --git a/tests/tests2/147_def_library.c b/tests/tests2/147_def_library.c new file mode 100644 index 00000000..8e1d9b3f --- /dev/null +++ b/tests/tests2/147_def_library.c @@ -0,0 +1,21 @@ +#ifdef DEF_LIBRARY_DLL + +__declspec(dllexport) int def_library_value(void) +{ + return 42; +} + +#else + +#include + +int def_library_value(void); + +int main(void) +{ + int value = def_library_value(); + printf("value: %d\n", value); + return value != 42; +} + +#endif diff --git a/tests/tests2/147_def_library.def.in b/tests/tests2/147_def_library.def.in new file mode 100644 index 00000000..aedf95d0 --- /dev/null +++ b/tests/tests2/147_def_library.def.in @@ -0,0 +1,3 @@ +LIBRARY "def library test" +EXPORTS + def_library_value diff --git a/tests/tests2/147_def_library.expect b/tests/tests2/147_def_library.expect new file mode 100644 index 00000000..84a64c37 --- /dev/null +++ b/tests/tests2/147_def_library.expect @@ -0,0 +1 @@ +value: 42 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 63a183c9..3e18000c 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -37,7 +37,7 @@ ifeq ($(CONFIG_bcheck),no) SKIP += 132_bound_test.test endif ifeq ($(CONFIG_dll),no) - SKIP += 113_btdll.test # no shared lib support yet + SKIP += 113_btdll.test 147_def_library.test # no shared lib support yet endif ifeq (-$(findstring gcc,$(CC))-,--) SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) @@ -81,6 +81,9 @@ endif ifneq (-$(ARCH)-$(CONFIG_WIN32)-,-arm64-yes-) SKIP += 145_winarm64_interlocked.test endif +ifneq ($(CONFIG_WIN32),yes) + SKIP += 147_def_library.test +endif # Some tests might need arguments ARGS = @@ -152,6 +155,14 @@ GEN-ALWAYS = $(TCC) -bt $1 a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=. -o $(basename $@).exe && \ ./$(basename $@).exe +# Verify quoted LIBRARY names and the default .dll extension in DEF files. +147_def_library.test: T1 = \ + cp $(SRC)/147_def_library.def.in 147_def_library.def && \ + $(TCC) -D DEF_LIBRARY_DLL -shared $1 -o "def library test.dll" && \ + $(TCC) $1 147_def_library.def -o $(basename $@).exe && \ + grep -a -q "def library test.dll" $(basename $@).exe && \ + ./$(basename $@).exe + 114_bound_signal.test: FLAGS += -b 114_bound_signal.test: NORUN = true # tcc -run does not support fork and -b and SELINUX 115_bound_setjmp.test: FLAGS += -b