RFR Checks in Pointer.cast(LayoutType)

John Rose john.r.rose at oracle.com
Tue Jun 19 00:57:18 UTC 2018


On Jun 18, 2018, at 7:41 AM, Sundararajan Athijegannathan <sundararajan.athijegannathan at oracle.com> wrote:
> 
> Pointer.cast(LayoutType) does not perform any checks as of now. Cast to any destination pointee LayoutType is allowed. I've added Layout.equals/.hashCode & simple checks in Pointer.cast(LayoutType) for now. For now, cast from any pointer to void* and vice versa is allowed. When pointee layouts are equal, the cast is allowed. Any other case results in exception.
> 
> Please review: http://cr.openjdk.java.net/~sundar/pointer_cast_checks/webrev.01/ <http://cr.openjdk.java.net/~sundar/pointer_cast_checks/webrev.01/>


Here's a nice quick review of void* casts in C and C++:
  https://eli.thegreenplace.net/2009/11/16/void-and-casts-in-c-and-c

C++ slightly increases type safety over C by allowing T* -> void*
without a cast (as C) but requiring an "ugly" explicit cast void* -> T*.

The asymmetry here captures the fact that casting to void* is a
type-forgetting operation (which is always safe, as far as it goes)
while casting to T* is a type-asserting operation (which can be unsafe).

We want a similar asymmetry in Panama user code:  Operations which
are provably safe should be easy to do, perhaps even an implicit conversion,
such as when calling out to a C function.  Meanwhile, operations which require
the user to assert a non-verifiable type (or bound) should require an distinct
and explicit operation.  As a rough guide, assignment conversions (where
"v = x" is allowed, based on the types of v and x) should be simple-looking
or even implicit, while cast conversions (where the assignment needs a cast
as "v = (T)x") should be easy to spot in user code.

The blog entry above has this useful quote from Stroustrup:

> "Functions using void* pointers typically exist at the very lowest level of the system,
> where real hardware resources are manipulated. Occurrences of void* at higher levels
> of the system should be viewed with suspicion because they are likely indicators of
> design errors."


For Panama, occurrences of type-asserting cast operators should be viewed with
similar suspicion, because they require careful proof that they will not cause a crash.
I expect that in many cases the type-asserting operations can be not only easily
spotted in user code, but also factored away into utility functions, allowing the
rest of the user code to be assumed safe without detailed inspection.

N.B. When I say "type asserting" I'm speaking generally, not of Java carrier types,
but mainly of layouts.  Asserting bounds is a similar issue:  Many (not all) of our
pointers come equipped with a backing memory region which "knows" its upper
and lower allocation bounds; operations on those pointers can be proven in-bounds
when appropriate runtime checks are added.  But when a void* pointer comes back
from C code, an explicit and distinctive operation may be needed to assign it,
not only a layout, but also bounds.  (Sometimes you can take the bounds from
a layout, sometimes not.)

Maurizio mentioned an idea this morning, to put the unsafe type-asserting
(and bounds-asserting) operations on static functions, rather than in the
"fluent" API of Pointer.  I think that might work out.  Failing that, we should
have a naming convention which makes it really clear which methods are
potentially dangerous and require extra analysis.

To get back to the current webrev:  It's a move in the right direction, but
we're going to need to separate the safe conversions from the unsafe ones.

— John


More information about the panama-dev mailing list