On Fri, 1 Aug 2025, Corinna Vinschen wrote: > On Aug 1 10:00, Corinna Vinschen wrote: > > On Jul 31 14:05, Jeremy Drake via Cygwin-patches wrote: > > > 3) running from dynamically loaded DLL's startup > > > newu would contain values from exe's startup, not zero, so would always > > > write the new pointers to cxx_malloc, memory corruption. > >
Duh, /* Likewise for the C++ memory operators, if any, but not if we were dlopen()'d, as we might get dlclose()'d and that would leave stale function pointers behind. */ if (newu && newu->cxx_malloc && !__dynamically_loaded) { > Ah, ok, but then again, in this case a check against the actual version > instead of checking just against != 0 should do it, shouldn't it? That's better for readability I think. I'll prepare a patch based on your suggestion > Like this: > > diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc > index 69c233c24759..a272208139ab 100644 > --- a/winsup/cygwin/dcrt0.cc > +++ b/winsup/cygwin/dcrt0.cc > @@ -724,6 +724,14 @@ dll_crt0_0 () > lock_process::init (); > user_data->impure_ptr = _impure_ptr; > user_data->impure_ptr_ptr = &_impure_ptr; > + /* DLL version info is used by newer _cygwin_crt0_common to handle > + certain issues in a forward compatible way. _cygwin_crt0_common > + overwrites these values with the application's version info at the > + time of building the app, as usual. */ > + user_data->dll_major = cygwin_version.dll_major; > + user_data->dll_minor = cygwin_version.dll_minor; > + user_data->api_major = cygwin_version.api_major; > + user_data->api_minor = cygwin_version.api_minor; > > DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), > GetCurrentProcess (), &hMainThread, > diff --git a/winsup/cygwin/include/cygwin/version.h > b/winsup/cygwin/include/cygwin/version.h > index f3321020f72e..00eedeb27ab4 100644 > --- a/winsup/cygwin/include/cygwin/version.h > +++ b/winsup/cygwin/include/cygwin/version.h > @@ -36,6 +36,9 @@ details. */ > #define CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS \ > (CYGWIN_VERSION_USER_API_VERSION_COMBINED >= 272) > > +#define CYGWIN_VERSION_CHECK_FOR_CXX17_OVERLOADS(u) \ > + (CYGWIN_VERSION_PER_PROCESS_API_VERSION_COMBINED (u) >= 359) > + > /* API_MAJOR 0.0: Initial version. API_MINOR changes: > 1: Export cygwin32_ calls as cygwin_ as well. > 2: Export j1, jn, y1, yn. > diff --git a/winsup/cygwin/lib/_cygwin_crt0_common.cc > b/winsup/cygwin/lib/_cygwin_crt0_common.cc > index 5900e6315dbe..312cba5756c0 100644 > --- a/winsup/cygwin/lib/_cygwin_crt0_common.cc > +++ b/winsup/cygwin/lib/_cygwin_crt0_common.cc > @@ -124,6 +124,9 @@ _cygwin_crt0_common (MainFunc f, per_process *u) > { > per_process *newu = (per_process *) cygwin_internal (CW_USER_DATA); > bool uwasnull; > + bool new_dll_with_additional_operators = > + newu ? CYGWIN_VERSION_CHECK_FOR_CXX17_OVERLOADS (newu) > + : false; > > /* u is non-NULL if we are in a DLL, and NULL in the main exe. > newu is the Cygwin DLL's internal per_process and never NULL. */ > @@ -190,18 +193,21 @@ _cygwin_crt0_common (MainFunc f, per_process *u) > CONDITIONALLY_OVERRIDE(oper_new___nt); > CONDITIONALLY_OVERRIDE(oper_delete_nt); > CONDITIONALLY_OVERRIDE(oper_delete___nt); > - CONDITIONALLY_OVERRIDE(oper_delete_sz); > - CONDITIONALLY_OVERRIDE(oper_delete___sz); > - CONDITIONALLY_OVERRIDE(oper_new_al); > - CONDITIONALLY_OVERRIDE(oper_new___al); > - CONDITIONALLY_OVERRIDE(oper_delete_al); > - CONDITIONALLY_OVERRIDE(oper_delete___al); > - CONDITIONALLY_OVERRIDE(oper_delete_sz_al); > - CONDITIONALLY_OVERRIDE(oper_delete___sz_al); > - CONDITIONALLY_OVERRIDE(oper_new_al_nt); > - CONDITIONALLY_OVERRIDE(oper_new___al_nt); > - CONDITIONALLY_OVERRIDE(oper_delete_al_nt); > - CONDITIONALLY_OVERRIDE(oper_delete___al_nt); > + if (new_dll_with_additional_operators) > + { > + CONDITIONALLY_OVERRIDE(oper_delete_sz); > + CONDITIONALLY_OVERRIDE(oper_delete___sz); > + CONDITIONALLY_OVERRIDE(oper_new_al); > + CONDITIONALLY_OVERRIDE(oper_new___al); > + CONDITIONALLY_OVERRIDE(oper_delete_al); > + CONDITIONALLY_OVERRIDE(oper_delete___al); > + CONDITIONALLY_OVERRIDE(oper_delete_sz_al); > + CONDITIONALLY_OVERRIDE(oper_delete___sz_al); > + CONDITIONALLY_OVERRIDE(oper_new_al_nt); > + CONDITIONALLY_OVERRIDE(oper_new___al_nt); > + CONDITIONALLY_OVERRIDE(oper_delete_al_nt); > + CONDITIONALLY_OVERRIDE(oper_delete___al_nt); > + } > /* Now update the resulting set into the global redirectors. */ > *newu->cxx_malloc = __cygwin_cxx_malloc; CONDITIIONALLY_OVERRIDE macro would need to be adjusted also so that these are assigned into the newu->cxx_malloc directly, and the wholesale copy of the struct is not done anymore since that depends on how large the compiler thinks the struct is.