Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions ext/pdo_sqlite/tests/pdo_sqlite_createfunction_003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
PDO_sqlite: Testing sqliteCreateFunction() with reflection
--SKIPIF--
<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
--FILE--
<?php

$db = new pdo('sqlite::memory:');

$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)');

$db->query('INSERT INTO foobar VALUES (NULL, "PHP")');
$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")');

$method = new ReflectionMethod($db, 'sqliteCreateFunction');
$method->invoke($db, 'testing', function($v) { return strtolower($v); }, 1);

foreach ($db->query('SELECT testing(name) FROM foobar') as $row) {
var_dump($row);
}

$db->query('DROP TABLE foobar');

?>
--EXPECTF--
array(2) {
["testing(name)"]=>
string(3) "php"
[0]=>
string(3) "php"
}
array(2) {
["testing(name)"]=>
string(4) "php6"
[0]=>
string(4) "php6"
}
17 changes: 17 additions & 0 deletions ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -2954,6 +2954,8 @@ ZEND_METHOD(reflection_method, __construct)
size_t name_len, tmp_len;
zval ztmp;

const zend_object_handlers *obj_handlers = NULL;

if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
return;
Expand Down Expand Up @@ -2996,6 +2998,7 @@ ZEND_METHOD(reflection_method, __construct)

case IS_OBJECT:
ce = Z_OBJCE_P(classname);
obj_handlers = Z_OBJ_HT_P(classname);
break;

default:
Expand All @@ -3017,6 +3020,20 @@ ZEND_METHOD(reflection_method, __construct)
&& (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
{
/* do nothing, mptr already set */
} else if (obj_handlers != NULL && obj_handlers->get_method != NULL) {
// a get_method object handler exists, so try to get the method from it
zend_string *method_string = zend_string_init(lcname, name_len, 0);

mptr = obj_handlers->get_method(&Z_OBJ_P(classname), method_string, NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this throw for inaccessible methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't touched this in a while, zend_std_get_method would? What would be the best way to reconcile either letting get_method handle throwing an error or otherwise throwing the exception below?

I might be misunderstanding though 🙂

zend_string_efree(method_string);

if (mptr == NULL) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
return;
}

} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0,
Expand Down