diff --git a/ext/queue/beanstalk.c b/ext/queue/beanstalk.c index 5b3d1b15d08..cc8b1e30246 100644 --- a/ext/queue/beanstalk.c +++ b/ext/queue/beanstalk.c @@ -74,7 +74,7 @@ PHALCON_INIT_CLASS(Phalcon_Queue_Beanstalk){ */ PHP_METHOD(Phalcon_Queue_Beanstalk, __construct){ - zval *options = NULL, *parameters = NULL; + zval *options = NULL, *parameters = NULL, *tmp; PHALCON_MM_GROW(); @@ -86,20 +86,26 @@ PHP_METHOD(Phalcon_Queue_Beanstalk, __construct){ if (Z_TYPE_P(options) != IS_ARRAY) { PHALCON_INIT_VAR(parameters); - array_init(parameters); + array_init_size(parameters, 2); } else { - PHALCON_CPY_WRT(parameters, options); + PHALCON_CPY_WRT_CTOR(parameters, options); } - if (!phalcon_array_isset_string(parameters, SS("host"))) { - phalcon_array_update_string_string(¶meters, SL("host"), SL("127.0.0.1"), PH_SEPARATE); + + if (!phalcon_array_isset_string_fetch(&tmp, parameters, SS("host"))) { + phalcon_array_update_string_string(¶meters, SL("host"), SL("127.0.0.1"), 0); + } + else { + convert_to_string(tmp); } - if (!phalcon_array_isset_string(parameters, SS("port"))) { - phalcon_array_update_string_long(¶meters, SL("port"), 11300, PH_SEPARATE); + if (!phalcon_array_isset_string_fetch(&tmp, parameters, SS("port"))) { + phalcon_array_update_string_long(¶meters, SL("port"), 11300, 0); + } + else { + convert_to_long(tmp); } phalcon_update_property_this(this_ptr, SL("_parameters"), parameters TSRMLS_CC); - PHALCON_MM_RESTORE(); } @@ -600,3 +606,35 @@ PHP_METHOD(Phalcon_Queue_Beanstalk, disconnect){ RETURN_TRUE; } +PHP_METHOD(Phalcon_Queue_Beanstalk, __sleep){ + + array_init_size(return_value, 1); + add_next_index_string(return_value, "_parameters", 1); +} + +PHP_METHOD(Phalcon_Queue_Beanstalk, __wakeup){ + + zval *params, *host, *port; + int fail; + + zend_update_property_null(phalcon_queue_beanstalk_ce, getThis(), SL("_connection") TSRMLS_CC); + + params = phalcon_fetch_nproperty_this(this_ptr, SL("_parameters"), PH_NOISY_CC); + if ( + Z_TYPE_P(params) != IS_ARRAY + || !phalcon_array_isset_string_fetch(&host, params, SS("host")) + || !phalcon_array_isset_string_fetch(&port, params, SS("port")) + ) { + fail = 1; + } + else if (Z_TYPE_P(host) != IS_STRING || Z_TYPE_P(port) != IS_LONG) { + fail = 1; + } + else { + fail = 0; + } + + if (fail) { + zend_throw_exception_ex(phalcon_exception_ce, 0 TSRMLS_CC, "Invalid serialization data"); + } +} diff --git a/ext/queue/beanstalk.h b/ext/queue/beanstalk.h index 6d957239c3d..928c45ec9a7 100644 --- a/ext/queue/beanstalk.h +++ b/ext/queue/beanstalk.h @@ -32,6 +32,8 @@ PHP_METHOD(Phalcon_Queue_Beanstalk, readStatus); PHP_METHOD(Phalcon_Queue_Beanstalk, read); PHP_METHOD(Phalcon_Queue_Beanstalk, write); PHP_METHOD(Phalcon_Queue_Beanstalk, disconnect); +PHP_METHOD(Phalcon_Queue_Beanstalk, __sleep); +PHP_METHOD(Phalcon_Queue_Beanstalk, __wakeup); ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_queue_beanstalk___construct, 0, 0, 0) ZEND_ARG_INFO(0, options) @@ -70,6 +72,8 @@ PHALCON_INIT_FUNCS(phalcon_queue_beanstalk_method_entry){ PHP_ME(Phalcon_Queue_Beanstalk, read, arginfo_phalcon_queue_beanstalk_read, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Queue_Beanstalk, write, NULL, ZEND_ACC_PROTECTED) PHP_ME(Phalcon_Queue_Beanstalk, disconnect, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Queue_Beanstalk, __sleep, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Queue_Beanstalk, __wakeup, NULL, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/ext/tests/issue-1635.phpt b/ext/tests/issue-1635.phpt new file mode 100644 index 00000000000..836920d8ad8 --- /dev/null +++ b/ext/tests/issue-1635.phpt @@ -0,0 +1,73 @@ +--TEST-- +Safe serialization/unserialization of Phalcon\Beanstalk\Queue - https://github.com/phalcon/cphalcon/pull/1635 +--SKIPIF-- + +--FILE-- +_parameters; + } + + public function getConnection() + { + return $this->_connection; + } + + public function setParams($v) + { + $this->_parameters = $v; + } + + public function setConnection($v) + { + $this->_connection = $v; + } +} + +$x = new \Test(array('host' => 127, 'port' => '11300')); +var_dump($x->getParams()); + +$x->setConnection(123.0); +assert($x->getConnection() === 123.0); +var_export(serialize($x)); +echo PHP_EOL; + +$s = 'O:4:"Test":2:{s:14:"' . "\0" . '*' . "\0" . '_connection";d:123;s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"host";s:3:"127";s:4:"port";i:11300;}}'; +$x = unserialize($s); +var_dump($x->getConnection()); + +$samples = array( + 'O:4:"Test":1:{s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"Host";s:3:"127";s:4:"port";i:11300;}}', + 'O:4:"Test":1:{s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"host";s:3:"127";s:4:"Port";i:11300;}}', + 'O:4:"Test":1:{s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"host";i:127;s:4:"port";i:11300;}}', + 'O:4:"Test":1:{s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"host";s:3:"127";s:4:"port";s:5:"11300";}}', +); + +foreach ($samples as $sample) { + try { + unserialize($sample); + assert(false); + } + catch (\Phalcon\Exception $e) { + echo $e->getMessage(), PHP_EOL; + } +} + +?> +--EXPECT-- +array(2) { + ["host"]=> + string(3) "127" + ["port"]=> + int(11300) +} +'O:4:"Test":1:{s:14:"' . "\0" . '*' . "\0" . '_parameters";a:2:{s:4:"host";s:3:"127";s:4:"port";i:11300;}}' +NULL +Invalid serialization data +Invalid serialization data +Invalid serialization data +Invalid serialization data