Skip to content

Commit b593c87

Browse files
Merge pull request #553 from CopernicaMarketingSoftware/serialize-parent
Fixed issue with overridden serialize method
2 parents 77fea0e + f502528 commit b593c87

File tree

1 file changed

+74
-26
lines changed

1 file changed

+74
-26
lines changed

zend/classimpl.cpp

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,20 +1320,53 @@ zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *obje
13201320
*/
13211321
int ClassImpl::serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data)
13221322
{
1323-
// get the serializable object
1324-
Serializable *serializable = dynamic_cast<Serializable*>(ObjectImpl::find(object)->object());
1325-
13261323
// user may throw an exception in the serialize() function
13271324
try
13281325
{
1329-
// call the serialize method on the object
1330-
auto value = serializable->serialize();
1331-
1332-
// allocate the buffer, and copy the data into it (the zend engine will
1333-
// (hopefully) clean up the data for us - the default serialize method does
1334-
// it like this too)
1335-
*buffer = (unsigned char*)estrndup(value.c_str(), value.size());
1336-
*buf_len = value.size();
1326+
// get the base object
1327+
Base *base = dynamic_cast<Base*>(ObjectImpl::find(object)->object());
1328+
1329+
// get the class-entry
1330+
zend_class_entry *ce = Z_OBJCE_P(object);
1331+
1332+
// we are going to check if the serialize method was overridden in user-space
1333+
zend_function *func = (zend_function *)zend_hash_str_find_ptr(&ce->function_table, "serialize", sizeof("serialize")-1);
1334+
1335+
// do we have a user-space alternative?
1336+
if (func && func->type == ZEND_USER_FUNCTION)
1337+
{
1338+
// construct object to make the call
1339+
Php::Object self(ce, base);
1340+
1341+
// get the serialized string
1342+
auto value = self.call("serialize");
1343+
1344+
// make sure the returned value is indeed a string
1345+
value.setType(Type::String);
1346+
1347+
// allocate the buffer, and copy the data into it (the zend engine will
1348+
// (hopefully) clean up the data for us - the default serialize method does
1349+
// it like this too)
1350+
*buffer = (unsigned char*)estrndup(value.rawValue(), value.size());
1351+
*buf_len = value.size();
1352+
}
1353+
else
1354+
{
1355+
// get the base object
1356+
Serializable *serializable = dynamic_cast<Serializable*>(base);
1357+
1358+
// call the serialize method on the object
1359+
auto value = serializable->serialize();
1360+
1361+
// allocate the buffer, and copy the data into it (the zend engine will
1362+
// (hopefully) clean up the data for us - the default serialize method does
1363+
// it like this too)
1364+
*buffer = (unsigned char*)estrndup(value.c_str(), value.size());
1365+
*buf_len = value.size();
1366+
}
1367+
1368+
// done
1369+
return SUCCESS;
13371370
}
13381371
catch (Throwable &throwable)
13391372
{
@@ -1343,9 +1376,6 @@ int ClassImpl::serialize(zval *object, unsigned char **buffer, size_t *buf_len,
13431376
// unreachable
13441377
return FAILURE;
13451378
}
1346-
1347-
// done
1348-
return SUCCESS;
13491379
}
13501380

13511381
/**
@@ -1358,17 +1388,38 @@ int ClassImpl::serialize(zval *object, unsigned char **buffer, size_t *buf_len,
13581388
*/
13591389
int ClassImpl::unserialize(zval *object, zend_class_entry *entry, const unsigned char *buffer, size_t buf_len, zend_unserialize_data *data)
13601390
{
1361-
// create the PHP object
1362-
object_init_ex(object, entry);
1363-
1364-
// turn this into a serializale
1365-
Serializable *serializable = dynamic_cast<Serializable*>(ObjectImpl::find(object)->object());
1366-
1367-
// user may throw an exception in the serialize() function
1391+
// user may throw an exception in the unserialize() function
13681392
try
13691393
{
1370-
// call the unserialize method on it
1371-
serializable->unserialize((const char *)buffer, buf_len);
1394+
// create the PHP object
1395+
object_init_ex(object, entry);
1396+
1397+
// get the base object
1398+
Base *base = dynamic_cast<Base*>(ObjectImpl::find(object)->object());
1399+
1400+
// we are going to check if the unserialize method was overridden in user-space
1401+
zend_function *func = (zend_function *)zend_hash_str_find_ptr(&entry->function_table, "unserialize", sizeof("unserialize")-1);
1402+
1403+
// do we have a user-space alternative?
1404+
if (func && func->type == ZEND_USER_FUNCTION)
1405+
{
1406+
// construct object to make the call
1407+
Php::Object self(entry, base);
1408+
1409+
// make the unserialize call
1410+
self.call("unserialize", Php::Value((const char *)buffer, buf_len));
1411+
}
1412+
else
1413+
{
1414+
// turn this into a serializale
1415+
Serializable *serializable = dynamic_cast<Serializable*>(base);
1416+
1417+
// call the unserialize method on it
1418+
serializable->unserialize((const char *)buffer, buf_len);
1419+
}
1420+
1421+
// done
1422+
return SUCCESS;
13721423
}
13731424
catch (Throwable &throwable)
13741425
{
@@ -1380,9 +1431,6 @@ int ClassImpl::unserialize(zval *object, zend_class_entry *entry, const unsigned
13801431
// unreachable
13811432
return FAILURE;
13821433
}
1383-
1384-
// done
1385-
return SUCCESS;
13861434
}
13871435

13881436
/**

0 commit comments

Comments
 (0)