On Mon, Sep 9, 2019 at 10:13 AM Stanislav Malyshev <smalys...@gmail.com>
wrote:


> > isset($err)
> > $err[0] != null
> > -> is always true, regardless of whether func as assigned an error or not
> >
> > $err[0];
> > -> segfault
>
> This is a bit confusing - if $err[0] segfaults, how it can be != null?
> Does this behave differently in different contexts? Anyway, it shouldn't
> probably segfault in any case, so this looks like a bug.
>

I think there are a few disconnected issues. One is that checking something
for being NULL is a bit tricky with the given API and the other is that the
API around FFI\CData is a bit inconsistent and tricky to use.

Given

$err = $ffi->new("Error*");

what the library does is assume that $err is now a pointer to an array
(which is what C does I guess), but yet, there seems to be a bit of an
issue with actually accessing that array (if it's set to NULL) - and also,
don't use var_dump() to inspect it - that's deceptive because there's a
debug_info handler that knows ore than the actual field accessors (which
too makes this more complicated than needed).

So. Let's assume that in

$err = $ffi->new("Error*");
$ffi->func(FFI::addr($err));

func() sets that argument to NULL, then

$f = $err[0];
var_dump(gettype($f));

returns "object" - so the zeroth index exists (hence the isset being true).

However there's also
$f = $err->{0};

which normally would throw "Attempt to read undefined field '0' of C
struct/union" but because $err is seen as an array, accessing a property
named 0 is possible, but then a second null check will happen via
https://github.com/php/php-src/blob/09e9c4f3c11a875c67334578621084f156155307/ext/ffi/ffi.c#L1103-L1107
and
you get "NULL pointer dereference" instead.

I believe this difference between [0] and {0} shouldn't exist.

And even aside of that, I see no way in which user-code can ever check any
reference for NULL because any access of a Cdata property or index that's
happen to be set to NULL will either segfault, throw or fail a comparison
in PHP because Cdata instances, according to PHP's type conversion rules,
always convert to something that compares truthy when put in boolean
context.

The inconsistency between [] and {} aside, I believe there should be an
FFI::isNull() static method or a Cdata::isNull() instance method that allow
user-code to check things for being NULL. Or the throw in the code I liked
to above is removed, but that would leave the inconsistency between [] and
{}

Or maybe I'm just overlooking something and there's a simple way to check
something for being NULL, but if there is, it IMHO needs better docs.

Philip

Reply via email to