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.

Reply via email to