Commit 58b4cc2df0c for php

commit 58b4cc2df0cba170bcfdf6f71234c0a21af948d2
Author: Kamil Tekiela <tekiela246@gmail.com>
Date:   Wed Sep 30 17:55:52 2026 +0100

    Remove the mysqlnd_reverse_api feature (#21409)

diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index d7263bb5cda..fa905cb1e53 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -52,6 +52,12 @@ PHP 8.7 INTERNALS UPGRADE NOTES
 3. Module changes
 ========================

+- MySQLi:
+  . Removed the reverse API. The mysqlnd_reverse_api.h header, the
+    MYSQLND_REVERSE_API struct and the functions zval_to_mysqlnd(),
+    mysqlnd_reverse_api_register_api() and mysqlnd_reverse_api_get_api_list()
+    no longer exist.
+
 - Standard:
   . php_explode() now takes a HashTable* instead of a zval* to store the
     resulting parts. It already expected the zval* to be IS_ARRAY.
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 5e6319ae77c..34479b84990 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -391,29 +391,6 @@ PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *class_type
 }
 /* }}} */

-#include "ext/mysqlnd/mysqlnd_reverse_api.h"
-static MYSQLND *mysqli_convert_zv_to_mysqlnd(zval * zv)
-{
-	if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), mysqli_link_class_entry)) {
-		MY_MYSQL *mysql;
-		MYSQLI_RESOURCE  *my_res;
-		mysqli_object *intern = Z_MYSQLI_P(zv);
-		if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
-			/* We know that we have a mysqli object, so this failure should be emitted */
-			zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(intern->zo.ce->name));
-			return NULL;
-		}
-		mysql = (MY_MYSQL *)(my_res->ptr);
-		return mysql ? mysql->mysql : NULL;
-	}
-	return NULL;
-}
-
-static const MYSQLND_REVERSE_API mysqli_reverse_api = {
-	&mysqli_module_entry,
-	mysqli_convert_zv_to_mysqlnd
-};
-
 static PHP_INI_MH(OnUpdateDefaultPort)
 {
 	zend_long value = ZEND_ATOL(ZSTR_VAL(new_value));
@@ -536,8 +513,6 @@ PHP_MINIT_FUNCTION(mysqli)

 	register_mysqli_symbols(module_number);

-	mysqlnd_reverse_api_register_api(&mysqli_reverse_api);
-
 	return SUCCESS;
 }
 /* }}} */
diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32
index e88b269c486..2d0654f8acb 100644
--- a/ext/mysqlnd/config.w32
+++ b/ext/mysqlnd/config.w32
@@ -15,7 +15,6 @@ if (PHP_MYSQLND != "no") {
 			"mysqlnd_driver.c " +
 			"mysqlnd_ext_plugin.c " +
 			"mysqlnd_loaddata.c " +
-			"mysqlnd_reverse_api.c " +
 			"mysqlnd_plugin.c " +
 			"mysqlnd_protocol_frame_codec.c " +
 			"mysqlnd_ps.c " +
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 800677f8d73..8a83a16327f 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -54,7 +54,6 @@ if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then
     mysqlnd_read_buffer.c
     mysqlnd_result_meta.c
     mysqlnd_result.c
-    mysqlnd_reverse_api.c
     mysqlnd_statistics.c
     mysqlnd_vio.c
     mysqlnd_wireprotocol.c
diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c
index deef03b9a3c..4c2d584e7ba 100644
--- a/ext/mysqlnd/mysqlnd_driver.c
+++ b/ext/mysqlnd/mysqlnd_driver.c
@@ -24,7 +24,6 @@
 #include "mysqlnd_priv.h"
 #include "mysqlnd_statistics.h"
 #include "mysqlnd_debug.h"
-#include "mysqlnd_reverse_api.h"
 #include "mysqlnd_ext_plugin.h"

 static bool mysqlnd_library_initted = FALSE;
@@ -57,7 +56,6 @@ PHPAPI void mysqlnd_library_end(void)
 		mysqlnd_stats_end(mysqlnd_global_stats, 1);
 		mysqlnd_global_stats = NULL;
 		mysqlnd_library_initted = FALSE;
-		mysqlnd_reverse_api_end();
 	}
 }
 /* }}} */
@@ -84,8 +82,6 @@ PHPAPI void mysqlnd_library_init(void)
 		mysqlnd_debug_trace_plugin_register();
 		mysqlnd_register_builtin_authentication_plugins();

-		mysqlnd_reverse_api_init();
-
 #if MYSQLND_CHARSETS_SANITY_CHECK == 1
 		void mysqlnd_charsets_sanity_check(void);
 		mysqlnd_charsets_sanity_check();
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.c b/ext/mysqlnd/mysqlnd_reverse_api.c
deleted file mode 100644
index 539c8adaaa6..00000000000
--- a/ext/mysqlnd/mysqlnd_reverse_api.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-  +----------------------------------------------------------------------+
-  | Copyright © The PHP Group and Contributors.                          |
-  +----------------------------------------------------------------------+
-  | This source file is subject to the Modified BSD License that is      |
-  | bundled with this package in the file LICENSE, and is available      |
-  | through the World Wide Web at <https://www.php.net/license/>.        |
-  |                                                                      |
-  | SPDX-License-Identifier: BSD-3-Clause                                |
-  +----------------------------------------------------------------------+
-  | Authors: Andrey Hristov <andrey@php.net>                             |
-  |          Johannes Schlüter <johannes@php.net>                        |
-  |          Ulf Wendel <uw@php.net>                                     |
-  +----------------------------------------------------------------------+
-*/
-
-#include "php.h"
-#include "mysqlnd.h"
-#include "mysqlnd_priv.h"
-#include "mysqlnd_debug.h"
-#include "mysqlnd_reverse_api.h"
-
-
-static HashTable mysqlnd_api_ext_ht;
-
-
-/* {{{ mysqlnd_reverse_api_init */
-PHPAPI void
-mysqlnd_reverse_api_init(void)
-{
-	zend_hash_init(&mysqlnd_api_ext_ht, 3, NULL, NULL, 1);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_reverse_api_end */
-PHPAPI void
-mysqlnd_reverse_api_end(void)
-{
-	zend_hash_destroy(&mysqlnd_api_ext_ht);
-}
-/* }}} */
-
-
-/* {{{ myslqnd_get_api_extensions */
-PHPAPI HashTable *
-mysqlnd_reverse_api_get_api_list(void)
-{
-	return &mysqlnd_api_ext_ht;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_reverse_api_register_api */
-PHPAPI void
-mysqlnd_reverse_api_register_api(const MYSQLND_REVERSE_API * apiext)
-{
-	zend_hash_str_add_ptr(&mysqlnd_api_ext_ht, apiext->module->name, strlen(apiext->module->name), (void*)apiext);
-}
-/* }}} */
-
-
-/* {{{ zval_to_mysqlnd */
-PHPAPI MYSQLND *
-zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities)
-{
-	MYSQLND_REVERSE_API *api;
-	ZEND_HASH_MAP_FOREACH_PTR(&mysqlnd_api_ext_ht, api) {
-		if (api->conversion_cb) {
-			MYSQLND *retval = api->conversion_cb(zv);
-			if (retval) {
-				if (retval->data) {
-					*save_client_api_capabilities = retval->data->m->negotiate_client_api_capabilities(retval->data, client_api_capabilities);
-				}
-				return retval;
-			}
-		}
-	} ZEND_HASH_FOREACH_END();
-	return NULL;
-}
-/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.h b/ext/mysqlnd/mysqlnd_reverse_api.h
deleted file mode 100644
index 843fa728aac..00000000000
--- a/ext/mysqlnd/mysqlnd_reverse_api.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-  +----------------------------------------------------------------------+
-  | Copyright © The PHP Group and Contributors.                          |
-  +----------------------------------------------------------------------+
-  | This source file is subject to the Modified BSD License that is      |
-  | bundled with this package in the file LICENSE, and is available      |
-  | through the World Wide Web at <https://www.php.net/license/>.        |
-  |                                                                      |
-  | SPDX-License-Identifier: BSD-3-Clause                                |
-  +----------------------------------------------------------------------+
-  | Authors: Andrey Hristov <andrey@php.net>                             |
-  |          Ulf Wendel <uw@php.net>                                     |
-  |          Georg Richter <georg@php.net>                               |
-  +----------------------------------------------------------------------+
-*/
-
-#ifndef MYSQLND_REVERSE_API_H
-#define MYSQLND_REVERSE_API_H
-typedef struct st_mysqlnd_reverse_api
-{
-	zend_module_entry * module;
-	MYSQLND *(*conversion_cb)(zval * zv);
-} MYSQLND_REVERSE_API;
-
-
-PHPAPI void mysqlnd_reverse_api_init(void);
-PHPAPI void mysqlnd_reverse_api_end(void);
-
-PHPAPI HashTable * mysqlnd_reverse_api_get_api_list(void);
-
-PHPAPI void mysqlnd_reverse_api_register_api(const MYSQLND_REVERSE_API * apiext);
-PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities);
-
-#endif	/* MYSQLND_REVERSE_API_H */
diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c
index f8b2d72ebab..ebfbedcbf5c 100644
--- a/ext/mysqlnd/php_mysqlnd.c
+++ b/ext/mysqlnd/php_mysqlnd.c
@@ -21,7 +21,6 @@
 #include "mysqlnd_priv.h"
 #include "mysqlnd_debug.h"
 #include "mysqlnd_statistics.h"
-#include "mysqlnd_reverse_api.h"
 #include "ext/standard/info.h"
 #include "zend_smart_str.h"

@@ -57,23 +56,6 @@ mysqlnd_minfo_dump_loaded_plugins(zval *el, void * buf)
 /* }}} */


-/* {{{ mysqlnd_minfo_dump_api_plugins */
-static void
-mysqlnd_minfo_dump_api_plugins(smart_str * buffer)
-{
-	HashTable *ht = mysqlnd_reverse_api_get_api_list();
-	MYSQLND_REVERSE_API *ext;
-
-	ZEND_HASH_MAP_FOREACH_PTR(ht, ext) {
-		if (buffer->s) {
-			smart_str_appendc(buffer, ',');
-		}
-		smart_str_appends(buffer, ext->module->name);
-	} ZEND_HASH_FOREACH_END();
-}
-/* }}} */
-
-
 /* {{{ PHP_MINFO_FUNCTION */
 PHP_MINFO_FUNCTION(mysqlnd)
 {
@@ -118,11 +100,6 @@ PHP_MINFO_FUNCTION(mysqlnd)
 		smart_str_0(&tmp_str);
 		php_info_print_table_row(2, "Loaded plugins", tmp_str.s? ZSTR_VAL(tmp_str.s) : "");
 		smart_str_free(&tmp_str);
-
-		mysqlnd_minfo_dump_api_plugins(&tmp_str);
-		smart_str_0(&tmp_str);
-		php_info_print_table_row(2, "API Extensions", tmp_str.s? ZSTR_VAL(tmp_str.s) : "");
-		smart_str_free(&tmp_str);
 	}

 	php_info_print_table_end();
diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c
index fe5ebc7e6ed..dcf5d665372 100644
--- a/ext/pdo_mysql/pdo_mysql.c
+++ b/ext/pdo_mysql/pdo_mysql.c
@@ -57,31 +57,6 @@ ZEND_DECLARE_MODULE_GLOBALS(pdo_mysql)
 # endif
 #endif

-#ifdef PDO_USE_MYSQLND
-#include "ext/mysqlnd/mysqlnd_reverse_api.h"
-static MYSQLND * pdo_mysql_convert_zv_to_mysqlnd(zval * zv)
-{
-	if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), php_pdo_get_dbh_ce())) {
-		pdo_dbh_t * dbh = Z_PDO_DBH_P(zv);
-
-		ZEND_ASSERT(dbh);
-
-		if (dbh->driver != &pdo_mysql_driver) {
-			php_error_docref(NULL, E_WARNING, "Provided PDO instance is not using MySQL but %s", dbh->driver->driver_name);
-			return NULL;
-		}
-
-		return ((pdo_mysql_db_handle *)dbh->driver_data)->server;
-	}
-	return NULL;
-}
-
-static const MYSQLND_REVERSE_API pdo_mysql_reverse_api = {
-	&pdo_mysql_module_entry,
-	pdo_mysql_convert_zv_to_mysqlnd
-};
-#endif
-
 /* Returns the number of SQL warnings during the execution of the last statement */
 PHP_METHOD(Pdo_Mysql, getWarningCount)
 {
@@ -146,10 +121,6 @@ static PHP_MINIT_FUNCTION(pdo_mysql)
 	REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_LOCAL_INFILE_DIRECTORY", (zend_long)PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY);
 #endif

-#ifdef PDO_USE_MYSQLND
-	mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api);
-#endif
-
 	pdo_mysql_ce = register_class_Pdo_Mysql(pdo_dbh_ce);
 	pdo_mysql_ce->create_object = pdo_dbh_new;