From 64cc31d48682147f05dcf094e7e3ee825e4c1290 Mon Sep 17 00:00:00 2001 From: Cameron Porter Date: Sat, 15 Jun 2019 21:37:04 -0500 Subject: [PATCH 1/2] Change ReflectionMethod object constructiion. Support constructing a ReflectionMethod from an object that has a get_method handler that can be used to reflect methods that aren't in the class entry, such as PDO driver-specific methods. --- ext/reflection/php_reflection.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index c38160297d400..988f49dea0ba9 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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; @@ -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: @@ -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); + 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, From 9e7c5f522b42890115f9b9ee4ff12341a7b3d45b Mon Sep 17 00:00:00 2001 From: Cameron Porter Date: Sat, 15 Jun 2019 22:22:10 -0500 Subject: [PATCH 2/2] Add pdo_sqlite test. --- .../tests/pdo_sqlite_createfunction_003.phpt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 ext/pdo_sqlite/tests/pdo_sqlite_createfunction_003.phpt diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_003.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_003.phpt new file mode 100644 index 0000000000000..a8184f94b8d9d --- /dev/null +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_003.phpt @@ -0,0 +1,37 @@ +--TEST-- +PDO_sqlite: Testing sqliteCreateFunction() with reflection +--SKIPIF-- + +--FILE-- +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" +}