Issue 22218 - Dynamic casts across binary boundaries can easily fail
Summary: Dynamic casts across binary boundaries can easily fail
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: druntime (show other issues)
Version: D2
Hardware: All All
: P1 major
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2021-08-16 20:03 UTC by kinke
Modified: 2021-08-20 07:49 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description kinke 2021-08-16 20:03:33 UTC
If there are TypeInfo duplicates in multiple binaries of a process, e.g., from templates instantiated in multiple binaries, dynamic casts can fail.

E.g., the following code fails with LDC (v1.27) and GDC (v10.3) on Linux, somehow works with DMD on Linux though, and fails on Windows in general:

```
class C() {}

version (DLL)
{
    version (Windows)
    {
        import core.sys.windows.dll;
        mixin SimpleDllMain;
    }

    pragma(mangle, "foo")
    export Object foo(Object o)
    {
        assert(cast(C!()) o); // <-- fails here
        return new C!();
    }
}
else
{
    T getFunc(T)(const(char)* sym, string thisExePath)
    {
        import core.runtime : Runtime;

        version (Windows)
        {
            import core.sys.windows.winbase : GetProcAddress;
            return cast(T) Runtime.loadLibrary("dynamiccast.dll")
                .GetProcAddress(sym);
        }
        else version (Posix)
        {
            import core.sys.posix.dlfcn : dlsym;
            import core.stdc.string : strrchr;

            auto name = thisExePath ~ '\0';
            const pathlen = strrchr(name.ptr, '/') - name.ptr + 1;
            name = name[0 .. pathlen] ~ "dynamiccast.so";
            return cast(T) Runtime.loadLibrary(name)
                .dlsym(sym);
        }
        else static assert(0);
    }

    void main(string[] args)
    {
        auto c = new C!();

        auto o = getFunc!(Object function(Object))("foo", args[0])(c);
        assert(cast(C!()) o);
    }
}
```

To be built and run like this:

$ dmd -shared dynamiccast.d -version=DLL -ofdynamiccast.so -fPIC -defaultlib=libphobos2.so
$ dmd dynamiccast.d -ofdynamiccast -fPIC -defaultlib=libphobos2.so
$ ./dynamiccast

Related: https://issues.dlang.org/show_bug.cgi?id=7020
Comment 1 Dlang Bot 2021-08-16 20:08:54 UTC
@kinke updated dlang/druntime pull request #3543 "Fix Issue 22218 - Dynamic casts across binary boundaries can easily fail" fixing this issue:

- Fix Issue 22218
  
  Actually fixed by the previous commits, just fixing up the rt.cast_
  compile errors after the rebase.

https://github.com/dlang/druntime/pull/3543
Comment 2 Dlang Bot 2021-08-20 07:49:09 UTC
dlang/druntime pull request #3543 "Fix Issue 22218 - Dynamic casts across binary boundaries can easily fail" was merged into master:

- 861ab5bb4f5de95499909afb9fb7123c2bb94b91 by Martin Kinkelin:
  Fix Issue 22218
  
  Actually fixed by the previous commits, just fixing up the rt.cast_
  compile errors after the rebase.

https://github.com/dlang/druntime/pull/3543