Poisoning in HotSpot

Julian Waters tanksherman27 at gmail.com
Wed Nov 27 04:54:34 UTC 2024


Hi Kim,

Darn, that's unfortunate. There was an earlier prototype I had that
does solve this issue, but unfortunately the error message resulting
from someone trying to use a poisoned method is much less clear in
that one:

#include <type_traits>

#pragma warning(disable : 4624) // This warning is already disabled for HotSpot

// Poisoning malloc so it cannot be used in a program

#define FORBID_C_FUNCTION(signature, alternative, body)              \
inline namespace {
                            \
    template<bool enabled = false, std::enable_if_t<enabled, int> = 0> \
    [[gnu::always_inline]] inline signature noexcept { body }
         \
    [[deprecated(alternative)]] signature noexcept = delete;                   \
}

#define ALLOW_C_FUNCTION(name) name<true>

FORBID_C_FUNCTION(void *malloc(size_t size), "use os::malloc", return
::malloc(size);)

The example program that includes the header above:

#include <cstdlib>

int main() {
    void *ptr = ::malloc(size_t{1});
    free(ptr);
}

Will get the following compile error:

<source>: In function 'int main()':
<source>:20:25: error: call of overloaded 'malloc(size_t)' is ambiguous
   20 |     void *ptr = ::malloc(size_t{1});
        |
In file included from
/opt/compiler-explorer/gcc-trunk-20241126/include/c++/15.0.0/cstdlib:83,
                 from <source>:2:
/usr/include/stdlib.h:540:14: note: candidate: 'void* malloc(size_t)'
  540 | extern void *malloc (size_t __size) __THROW __attribute_malloc__
         |              ^~~~~~
<source>:17:25: note: candidate: 'void* {anonymous}::malloc(size_t)' (deleted)
   17 | FORBID_C_FUNCTION(void *malloc(size_t size), "use os::malloc",
return ::malloc(size);)
        |                         ^~~~~~
<source>:12:33: note: in definition of macro 'FORBID_C_FUNCTION'
   12 |     [[deprecated(alternative)]] signature noexcept = delete;           \
        |                                 ^~~~~~~~~

Unless ::malloc is wrapped in ALLOW_C_FUNCTION

As for the scoped attributes, for this particular case HotSpot has the
ALWAYSINLINE macro, which bypasses the issue of having unknown
attributes. They could be defined to the corresponding scoped
forceinline attribute that the compiler understands, which avoids
compile failures

best regards,
Julian


On Wed, Nov 27, 2024 at 12:56 AM Kim Barrett <kim.barrett at oracle.com> wrote:
>
> On 11/26/24 4:55 AM, Julian Waters wrote:
> > Hi all,
> >
> > It turned out in the review of
> > https://github.com/openjdk/jdk/pull/22069 that the poisoning mechanism
> > used in HotSpot can break when combined with LTO. Also, poisoning does
> > not work on Windows, at least not with the default Microsoft compiler
> > (Though, the Windows/gcc Port also disables FORBID_C_FUNCTION as
> > well). I've tried coming up with an alternative mechanism to poison
> > methods that works on any platform, but I'm unsure what to do with it
> > now. It can be viewed here: https://godbolt.org/z/PKMjjWTxz
> >
> > Any improvements that could be made to it? Should I continue this so
> > we can have a poisoning mechanism that works even while LTO is active?
>
> I think the approach taken in that link won't work, and can't. Try
>
> void* ptr = ::malloc(size_t(1))
>
> No "use of a deleted function" error from that. The problem is that a
> non-template exact match is a better match than any template in the overload
> set. So calling ::malloc with a size_t argument calls the clib function
> rather
> than the template in the anonymous namespace.
>
> There's also the "scoped attribute directive ignored" warnings. I remember
> reading something about scoped attributes not being as useful as one might
> think. Ah, here's part of the discussion:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86368
>


More information about the hotspot-dev mailing list