Skip to content

Commit c512e02

Browse files
author
Toon Schoenmakers
committed
Revert "Revert "Fix issue with derived classes, but only fix it for PHP 5.4 and up. Closes CopernicaMarketingSoftware#211""
This reverts commit fd806d0. Reverting the revert as I'm unable to reproduce the issue caused by this commit and it all seems to work fine..
1 parent fd806d0 commit c512e02

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

zend/classimpl.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,46 @@ ClassImpl::~ClassImpl()
3838
*/
3939
static ClassImpl *self(zend_class_entry *entry)
4040
{
41-
// we need the base class (in user space the class may have been overridden,
42-
// but we are not interested in these user space classes)
43-
while (entry->parent) entry = entry->parent;
44-
4541
#if PHP_VERSION_ID >= 50400
42+
43+
/**
44+
* somebody could have extended this class from PHP userland, in which
45+
* case trying to dereference the doc_comment would result in a disaster
46+
* because it does not point to a class implemented by PHP-CPP at all!
47+
*
48+
* if this happens we need to keep going until we find the object that
49+
* was implemented by us. For this we are going to make the assumption
50+
* that we are the only ones misusing the doc_comment the way we do.
51+
*
52+
* Usually the doc_comment is not set (it equals the nullptr) and if it
53+
* is set, the accompanying doc_comment_len should be non-zero to
54+
* indicate the number of characters in it.
55+
*/
56+
while (entry->parent && entry->info.user.doc_comment == nullptr && entry->info.user.doc_comment_len == 0)
57+
{
58+
// we did not create this class entry, but luckily we have a parent
59+
entry = entry->parent;
60+
}
61+
4662
// retrieve the comment (it has a pointer hidden in it to the ClassBase object)
4763
const char *comment = entry->info.user.doc_comment;
4864

4965
// the first byte of the comment is an empty string (null character), but
5066
// the next bytes contain a pointer to the ClassBase class
5167
return *((ClassImpl **)(comment + 1));
5268
#else
69+
70+
/**
71+
* This is likely not correct: If the class was extended using PHP-CPP
72+
* itself, we should retrieve the ClassImpl directly, however there is
73+
* no sane way to check this here, unlike in PHP 5.4.
74+
*
75+
* We therefore always go to the very base, of which we are sure that
76+
* we are the implementers. This way - at least - we don't cause any
77+
* segfaults.
78+
*/
79+
while (entry->parent) entry = entry->parent;
80+
5381
// on php 5.3 we store the pointer to impl after the name in the entry
5482
ClassImpl** impl = (ClassImpl**)(entry->name + 1 + entry->name_length);
5583

@@ -476,7 +504,7 @@ int ClassImpl::cast(zval *val, zval *retval, int type TSRMLS_DC)
476504

477505
// @todo do we turn into endless conversion if the __toString object returns 'this' ??
478506
// (and if it does: who cares? If the extension programmer is stupid, why do we have to suffer?)
479-
507+
480508
// is the original parameter overwritten?
481509
if (val == retval) zval_dtor(val);
482510

0 commit comments

Comments
 (0)