From 8b1e3943a0152a8f4a00d7ea836d039df22b4a03 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 6 Feb 2026 00:43:31 +0000 Subject: [PATCH 01/13] zend_highlight: mark char* cont --- Zend/zend_highlight.c | 4 ++-- Zend/zend_highlight.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index 5c3cd136d5807..c5fc874b9cb5f 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -79,8 +79,8 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini { zval token; int token_type; - char *last_color = syntax_highlighter_ini->highlight_html; - char *next_color; + const char *last_color = syntax_highlighter_ini->highlight_html; + const char *next_color; zend_printf("
", last_color);
 	/* highlight stuff coming back from zendlex() */
diff --git a/Zend/zend_highlight.h b/Zend/zend_highlight.h
index 04688d65132b2..adc1d3c8c81e0 100644
--- a/Zend/zend_highlight.h
+++ b/Zend/zend_highlight.h
@@ -30,11 +30,11 @@
 
 
 typedef struct _zend_syntax_highlighter_ini {
-	char *highlight_html;
-	char *highlight_comment;
-	char *highlight_default;
-	char *highlight_string;
-	char *highlight_keyword;
+	const char *highlight_html;
+	const char *highlight_comment;
+	const char *highlight_default;
+	const char *highlight_string;
+	const char *highlight_keyword;
 } zend_syntax_highlighter_ini;
 
 

From d5862628ea25d913bfa179029830a5bac7e18e14 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Fri, 6 Feb 2026 00:40:30 +0000
Subject: [PATCH 02/13] Audit zend_ini_string usage

---
 ext/openssl/openssl_backend_common.c |  8 ++++----
 ext/openssl/xp_ssl.c                 | 12 ++++++------
 ext/standard/basic_functions.c       |  5 ++---
 ext/zlib/zlib.c                      |  5 ++---
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c
index c0590c98acfb7..aeba4bb0beb6c 100644
--- a/ext/openssl/openssl_backend_common.c
+++ b/ext/openssl/openssl_backend_common.c
@@ -504,10 +504,10 @@ void php_openssl_set_cert_locations(zval *return_value)
 	add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env());
 	add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir());
 	add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area());
-	add_assoc_string(return_value, "ini_cafile",
-		zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0));
-	add_assoc_string(return_value, "ini_capath",
-		zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0));
+	add_assoc_str(return_value, "ini_cafile",
+		zend_string_copy(zend_ini_str(ZEND_STRL("openssl.cafile"), false)));
+	add_assoc_str(return_value, "ini_capath",
+		zend_string_copy(zend_ini_str(ZEND_STRL("openssl.capath"), false)));
 }
 
 X509 *php_openssl_x509_from_str(
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index bd174f30095c6..c6e711361a2fc 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -880,16 +880,16 @@ static long php_openssl_load_stream_cafile(X509_STORE *cert_store, const char *c
 static zend_result php_openssl_enable_peer_verification(SSL_CTX *ctx, php_stream *stream) /* {{{ */
 {
 	zval *val = NULL;
-	char *cafile = NULL;
-	char *capath = NULL;
+	const char *cafile = NULL;
+	const char *capath = NULL;
 	php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
 
 	GET_VER_OPT_STRING("cafile", cafile);
 	GET_VER_OPT_STRING("capath", capath);
 
 	if (cafile == NULL) {
-		cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0);
-		cafile = strlen(cafile) ? cafile : NULL;
+		const zend_string *cafile_str = zend_ini_str(ZEND_STRL("openssl.cafile"), false);
+		cafile = ZSTR_LEN(cafile_str) ? ZSTR_VAL(cafile_str) : NULL;
 	} else if (!sslsock->is_client) {
 		/* Servers need to load and assign CA names from the cafile */
 		STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(cafile);
@@ -902,8 +902,8 @@ static zend_result php_openssl_enable_peer_verification(SSL_CTX *ctx, php_stream
 	}
 
 	if (capath == NULL) {
-		capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0);
-		capath = strlen(capath) ? capath : NULL;
+		const zend_string *capath_str = zend_ini_str(ZEND_STRL("openssl.capath"), false);
+		capath = ZSTR_LEN(capath_str) ? ZSTR_VAL(capath_str) : NULL;
 	}
 
 	if (cafile || capath) {
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 0f802bc128a20..4bfcf3d77ead7 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -2020,17 +2020,16 @@ PHP_FUNCTION(ini_restore)
 PHP_FUNCTION(set_include_path)
 {
 	zend_string *new_value;
-	char *old_value;
 	zend_string *key;
 
 	ZEND_PARSE_PARAMETERS_START(1, 1)
 		Z_PARAM_PATH_STR(new_value)
 	ZEND_PARSE_PARAMETERS_END();
 
-	old_value = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
+	zend_string *old_value = zend_ini_str("include_path", sizeof("include_path") - 1, false);
 	/* copy to return here, because alter might free it! */
 	if (old_value) {
-		RETVAL_STRING(old_value);
+		RETVAL_STR_COPY(old_value);
 	} else {
 		RETVAL_FALSE;
 	}
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 4a6bb81899c91..7cab83fb8900a 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1267,7 +1267,6 @@ ZEND_GET_MODULE(php_zlib)
 static PHP_INI_MH(OnUpdate_zlib_output_compression)
 {
 	int int_value;
-	char *ini_value;
 	if (new_value == NULL) {
 		return FAILURE;
 	}
@@ -1279,9 +1278,9 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
 	} else {
 		int_value = (int) zend_ini_parse_quantity_warn(new_value, entry->name);
 	}
-	ini_value = zend_ini_string("output_handler", sizeof("output_handler") - 1, 0);
+	const zend_string *ini_value = zend_ini_str(ZEND_STRL("output_handler"), false);
 
-	if (ini_value && *ini_value && int_value) {
+	if (ini_value && ZSTR_LEN(ini_value) && int_value) {
 		php_error_docref("ref.outcontrol", E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
 		return FAILURE;
 	}

From 540a3ea265274ddf647e6f3bd631dea8df8e0ff1 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Fri, 6 Feb 2026 01:13:20 +0000
Subject: [PATCH 03/13] Audit INI_STR

---
 Zend/zend_fibers.c          |  4 ++--
 ext/com_dotnet/com_dotnet.c |  7 +++----
 ext/curl/interface.c        |  4 +---
 ext/standard/browscap.c     |  4 ++--
 ext/standard/dl.c           |  2 +-
 ext/standard/mail.c         |  6 +++---
 main/main.c                 |  4 ++--
 main/php_ini.c              |  2 +-
 sapi/phpdbg/phpdbg_prompt.c | 13 +++++--------
 9 files changed, 20 insertions(+), 26 deletions(-)

diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c
index d571a622e476b..4986e3a92b0b5 100644
--- a/Zend/zend_fibers.c
+++ b/Zend/zend_fibers.c
@@ -573,8 +573,8 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
 
 	/* Determine the current error_reporting ini setting. */
 	zend_long error_reporting = INI_INT("error_reporting");
-	/* If error_reporting is 0 and not explicitly set to 0, INI_STR returns a null pointer. */
-	if (!error_reporting && !INI_STR("error_reporting")) {
+	/* If error_reporting is 0 and not explicitly set to 0, zend_ini_str returns a null pointer. */
+	if (!error_reporting && !zend_ini_str(ZEND_STRL("error_reporting"), false)) {
 		error_reporting = E_ALL;
 	}
 
diff --git a/ext/com_dotnet/com_dotnet.c b/ext/com_dotnet/com_dotnet.c
index f8b4a828e154a..7e03887d01f5f 100644
--- a/ext/com_dotnet/com_dotnet.c
+++ b/ext/com_dotnet/com_dotnet.c
@@ -127,7 +127,6 @@ static HRESULT dotnet_bind_runtime(LPVOID FAR *ppv)
 	typedef HRESULT (STDAPICALLTYPE *cbtr_t)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
 	cbtr_t CorBindToRuntime;
 	OLECHAR *oleversion;
-	char *version;
 
 	mscoree = LoadLibraryA("mscoree.dll");
 	if (mscoree == NULL) {
@@ -140,11 +139,11 @@ static HRESULT dotnet_bind_runtime(LPVOID FAR *ppv)
 		return S_FALSE;
 	}
 
-	version = INI_STR("com.dotnet_version");
-	if (version == NULL || *version == '\0') {
+	const zend_string *version = zend_ini_str(ZEND_STRL("com.dotnet_version"), false);
+	if (version == NULL || ZSTR_LEN(version) == 0) {
 		oleversion = NULL;
 	} else {
-		oleversion = php_com_string_to_olestring(version, strlen(version), COMG(code_page));
+		oleversion = php_com_string_to_olestring(ZSTR_VAL(version), ZSTR_LEN(version), COMG(code_page));
 	}
 
 	hr = CorBindToRuntime(oleversion, NULL, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, ppv);
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 6328538241fe6..e33644a607d97 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -1100,8 +1100,6 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode)
    Set default options for a handle */
 static void _php_curl_set_default_options(php_curl *ch)
 {
-	char *cainfo;
-
 	curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS,        1L);
 	curl_easy_setopt(ch->cp, CURLOPT_VERBOSE,           0L);
 	curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
@@ -1114,7 +1112,7 @@ static void _php_curl_set_default_options(php_curl *ch)
 	curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120L);
 	curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20L); /* prevent infinite redirects */
 
-	cainfo = INI_STR("openssl.cafile");
+	const char* cainfo = INI_STR("openssl.cafile");
 	if (!(cainfo && cainfo[0] != '\0')) {
 		cainfo = INI_STR("curl.cainfo");
 	}
diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c
index 5009c7793688c..1a49d1c3eab8e 100644
--- a/ext/standard/browscap.c
+++ b/ext/standard/browscap.c
@@ -399,7 +399,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
 }
 /* }}} */
 
-static zend_result browscap_read_file(char *filename, browser_data *browdata, bool persistent) /* {{{ */
+static zend_result browscap_read_file(const char *filename, browser_data *browdata, bool persistent) /* {{{ */
 {
 	zend_file_handle fh;
 	browscap_parser_ctx ctx = {0};
@@ -499,7 +499,7 @@ PHP_INI_MH(OnChangeBrowscap)
 
 PHP_MINIT_FUNCTION(browscap) /* {{{ */
 {
-	char *browscap = INI_STR("browscap");
+	const char *browscap = INI_STR("browscap");
 
 #ifdef ZTS
 	ts_allocate_id(&browscap_globals_id, sizeof(browser_data), (ts_allocate_ctor) browscap_globals_ctor, NULL);
diff --git a/ext/standard/dl.c b/ext/standard/dl.c
index 31adbceac8c29..d69a1d3d48dff 100644
--- a/ext/standard/dl.c
+++ b/ext/standard/dl.c
@@ -114,7 +114,7 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
 	zend_module_entry *module_entry;
 	zend_module_entry *(*get_module)(void);
 	int error_type, slash_suffix = 0;
-	char *extension_dir;
+	const char *extension_dir;
 	char *err1, *err2;
 
 	if (type == MODULE_PERSISTENT) {
diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 395c7bb81d4f9..1eb1b2cee0758 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -437,7 +437,7 @@ static int php_mail_detect_multiple_crlf(const char *hdr) {
 PHPAPI bool php_mail(const char *to, const char *subject, const char *message, const char *headers, const zend_string *extra_cmd)
 {
 	FILE *sendmail;
-	char *sendmail_path = INI_STR("sendmail_path");
+	const char *sendmail_path = INI_STR("sendmail_path");
 	char *sendmail_cmd = NULL;
 	const zend_string *mail_log = zend_ini_str(ZEND_STRL("mail.log"), false);
 	const char *hdr = headers;
@@ -553,7 +553,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 	if (extra_cmd != NULL) {
 		spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, ZSTR_VAL(extra_cmd));
 	} else {
-		sendmail_cmd = sendmail_path;
+		sendmail_cmd = (char*)sendmail_path;
 	}
 
 #if PHP_SIGCHILD
@@ -701,7 +701,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 /* {{{ PHP_MINFO_FUNCTION */
 PHP_MINFO_FUNCTION(mail)
 {
-	char *sendmail_path = INI_STR("sendmail_path");
+	const char *sendmail_path = INI_STR("sendmail_path");
 
 #ifdef PHP_WIN32
 	if (!sendmail_path) {
diff --git a/main/main.c b/main/main.c
index 8062f92fe1bdb..739e8e2e00e6c 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1471,8 +1471,8 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c
 			if (PG(xmlrpc_errors)) {
 				php_printf("faultCode" ZEND_LONG_FMT "faultString%s:%s in %s on line %" PRIu32 "%s%s", PG(xmlrpc_error_number), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno, ZSTR_LEN(backtrace) ? "\nStack trace:\n" : "", ZSTR_VAL(backtrace));
 			} else {
-				char *prepend_string = INI_STR("error_prepend_string");
-				char *append_string = INI_STR("error_append_string");
+				const char *prepend_string = INI_STR("error_prepend_string");
+				const char *append_string = INI_STR("error_append_string");
 
 				if (PG(html_errors)) {
 					if (type == E_ERROR || type == E_PARSE) {
diff --git a/main/php_ini.c b/main/php_ini.c
index e464c05d1fcc1..800191285b87e 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -334,7 +334,7 @@ static void php_load_zend_extension_cb(void *arg)
 	} else {
 		DL_HANDLE handle;
 		char *libpath;
-		char *extension_dir = INI_STR("extension_dir");
+		const char *extension_dir = INI_STR("extension_dir");
 		int slash_suffix = 0;
 		char *err1, *err2;
 
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index 9566c1abd4eec..ca5fff6ee5908 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -1190,19 +1190,16 @@ static void add_zendext_info(zend_extension *ext) /* {{{ */ {
 #ifdef HAVE_LIBDL
 PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, const char **name) /* {{{ */ {
 	DL_HANDLE handle;
-	char *extension_dir;
-
-	extension_dir = INI_STR("extension_dir");
+	zend_string *extension_dir = zend_ini_str(ZEND_STRL("extension_dir"), false);
 
 	if (strchr(*path, '/') != NULL || strchr(*path, DEFAULT_SLASH) != NULL) {
 		/* path is fine */
-	} else if (extension_dir && extension_dir[0]) {
+	} else if (extension_dir && ZSTR_LEN(extension_dir)) {
 		char *libpath;
-		int extension_dir_len = strlen(extension_dir);
-		if (IS_SLASH(extension_dir[extension_dir_len-1])) {
-			spprintf(&libpath, 0, "%s%s", extension_dir, *path); /* SAFE */
+		if (IS_SLASH(ZSTR_VAL(extension_dir)[ZSTR_LEN(extension_dir-1)])) {
+			spprintf(&libpath, 0, "%s%s", ZSTR_VAL(extension_dir), *path); /* SAFE */
 		} else {
-			spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, *path); /* SAFE */
+			spprintf(&libpath, 0, "%s%c%s", ZSTR_VAL(extension_dir), DEFAULT_SLASH, *path); /* SAFE */
 		}
 		efree(*path);
 		*path = libpath;

From 7dff77527fe6e09df1b8ae5191b29bffa44dba5f Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Fri, 6 Feb 2026 01:17:04 +0000
Subject: [PATCH 04/13] Audit INI_ORIG_BOOL

---
 ext/tidy/tidy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c
index 9dcfb733a591f..829403d0e6ce4 100644
--- a/ext/tidy/tidy.c
+++ b/ext/tidy/tidy.c
@@ -873,7 +873,7 @@ static PHP_RINIT_FUNCTION(tidy)
 
 static PHP_RSHUTDOWN_FUNCTION(tidy)
 {
-	TG(clean_output) = INI_ORIG_BOOL("tidy.clean_output");
+	TG(clean_output) = zend_ini_parse_bool(zend_ini_str(ZEND_STRL("tidy.clean_output"), true));
 
 	return SUCCESS;
 }

From 49d89f11de0ff7edabd425eea80c6d3f61c16c44 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Fri, 6 Feb 2026 01:24:07 +0000
Subject: [PATCH 05/13] Update definitions of INI_BOOL macros

---
 Zend/zend_ini.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index d8d7f599f461e..b07bea6238706 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -194,12 +194,12 @@ END_EXTERN_C()
 #define INI_INT(name) zend_ini_long((name), strlen(name), 0)
 #define INI_FLT(name) zend_ini_double((name), strlen(name), 0)
 #define INI_STR(name) zend_ini_string_ex((name), strlen(name), 0, NULL)
-#define INI_BOOL(name) ((bool) INI_INT(name))
+#define INI_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), false))
 
 #define INI_ORIG_INT(name)	zend_ini_long((name), strlen(name), 1)
 #define INI_ORIG_FLT(name)	zend_ini_double((name), strlen(name), 1)
 #define INI_ORIG_STR(name)	zend_ini_string((name), strlen(name), 1)
-#define INI_ORIG_BOOL(name) ((bool) INI_ORIG_INT(name))
+#define INI_ORIG_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), true))
 
 #define REGISTER_INI_ENTRIES() zend_register_ini_entries_ex(ini_entries, module_number, type)
 #define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries_ex(module_number, type)

From 2eb0a1fc17e05657324c2154e92632980e0b4582 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Fri, 6 Feb 2026 01:32:40 +0000
Subject: [PATCH 06/13] zend_ini: mark zend_ini_string{_ex} as returning a
 const char*

---
 Zend/zend_ini.c | 4 ++--
 Zend/zend_ini.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index d8f1d4f50f95d..85739415feb32 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -491,7 +491,7 @@ ZEND_API double zend_ini_double(const char *name, size_t name_length, bool orig)
 }
 /* }}} */
 
-ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, bool orig, bool *exists) /* {{{ */
+ZEND_API const char *zend_ini_string_ex(const char *name, size_t name_length, bool orig, bool *exists) /* {{{ */
 {
 	zend_string *str = zend_ini_str_ex(name, name_length, orig, exists);
 
@@ -499,7 +499,7 @@ ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, bool ori
 }
 /* }}} */
 
-ZEND_API char *zend_ini_string(const char *name, size_t name_length, bool orig) /* {{{ */
+ZEND_API const char *zend_ini_string(const char *name, size_t name_length, bool orig) /* {{{ */
 {
 	zend_string *str = zend_ini_str(name, name_length, orig);
 
diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index b07bea6238706..3b91a5f7fe5b5 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -88,8 +88,8 @@ ZEND_API void display_ini_entries(zend_module_entry *module);
 
 ZEND_API zend_long zend_ini_long(const char *name, size_t name_length, bool orig);
 ZEND_API double zend_ini_double(const char *name, size_t name_length, bool orig);
-ZEND_API char *zend_ini_string(const char *name, size_t name_length, bool orig);
-ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, bool orig, bool *exists);
+ZEND_API const char *zend_ini_string(const char *name, size_t name_length, bool orig);
+ZEND_API const char *zend_ini_string_ex(const char *name, size_t name_length, bool orig, bool *exists);
 ZEND_API zend_string *zend_ini_str(const char *name, size_t name_length, bool orig);
 ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool orig, bool *exists);
 ZEND_API zend_string *zend_ini_get_value(zend_string *name);

From e37da49aec4ccbcf5860a9d80d07ba4d866462ba Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 13:25:51 +0000
Subject: [PATCH 07/13] Add new literal ini API and remove the INI_*() macros

---
 Zend/zend_fibers.c                   |  4 ++--
 Zend/zend_ini.h                      | 21 +++++++++++----------
 Zend/zend_multibyte.c                |  4 ++--
 ext/com_dotnet/com_dotnet.c          |  2 +-
 ext/curl/interface.c                 |  4 ++--
 ext/date/php_date.c                  |  8 ++++----
 ext/gd/gd.c                          |  2 +-
 ext/openssl/openssl_backend_common.c |  6 ++----
 ext/openssl/xp_ssl.c                 |  4 ++--
 ext/session/session.c                |  8 ++++----
 ext/soap/soap.c                      |  4 ++--
 ext/standard/basic_functions.c       | 14 +++++++-------
 ext/standard/browscap.c              |  4 ++--
 ext/standard/dl.c                    |  2 +-
 ext/standard/mail.c                  | 10 +++++-----
 ext/zlib/zlib.c                      |  2 +-
 main/main.c                          |  8 ++++----
 main/php_ini.c                       |  2 +-
 main/rfc1867.c                       |  4 ++--
 sapi/phpdbg/phpdbg_prompt.c          |  2 +-
 win32/sendmail.c                     |  8 ++++----
 21 files changed, 61 insertions(+), 62 deletions(-)

diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c
index 4986e3a92b0b5..248b4f401a71a 100644
--- a/Zend/zend_fibers.c
+++ b/Zend/zend_fibers.c
@@ -572,9 +572,9 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
 	zend_fiber *fiber = EG(active_fiber);
 
 	/* Determine the current error_reporting ini setting. */
-	zend_long error_reporting = INI_INT("error_reporting");
+	zend_long error_reporting = zend_ini_long_literal("error_reporting");
 	/* If error_reporting is 0 and not explicitly set to 0, zend_ini_str returns a null pointer. */
-	if (!error_reporting && !zend_ini_str(ZEND_STRL("error_reporting"), false)) {
+	if (!error_reporting && !zend_ini_str_literal("error_reporting")) {
 		error_reporting = E_ALL;
 	}
 
diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index 3b91a5f7fe5b5..d60b3425dcf0e 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -95,6 +95,17 @@ ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool
 ZEND_API zend_string *zend_ini_get_value(zend_string *name);
 ZEND_API bool zend_ini_parse_bool(const zend_string *str);
 
+#define zend_ini_bool_literal(name) zend_ini_parse_bool(zend_ini_str((name), sizeof("" name) - 1, false))
+#define zend_ini_long_literal(name) zend_ini_long((name), sizeof("" name) - 1, false)
+#define zend_ini_double_literal(name) zend_ini_double((name), sizeof("" name) - 1, false)
+#define zend_ini_str_literal(name) zend_ini_str((name), sizeof("" name) - 1, false)
+#define zend_ini_string_literal(name) zend_ini_string((name), sizeof("" name) - 1, false)
+
+#define INI_ORIG_INT(name)	zend_ini_long((name), strlen(name), 1)
+#define INI_ORIG_FLT(name)	zend_ini_double((name), strlen(name), 1)
+#define INI_ORIG_STR(name)	zend_ini_string((name), strlen(name), 1)
+#define INI_ORIG_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), true))
+
 /**
  * Parses an ini quantity
  *
@@ -191,16 +202,6 @@ END_EXTERN_C()
 	ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr, NULL, zend_ini_boolean_displayer_cb)
 #endif
 
-#define INI_INT(name) zend_ini_long((name), strlen(name), 0)
-#define INI_FLT(name) zend_ini_double((name), strlen(name), 0)
-#define INI_STR(name) zend_ini_string_ex((name), strlen(name), 0, NULL)
-#define INI_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), false))
-
-#define INI_ORIG_INT(name)	zend_ini_long((name), strlen(name), 1)
-#define INI_ORIG_FLT(name)	zend_ini_double((name), strlen(name), 1)
-#define INI_ORIG_STR(name)	zend_ini_string((name), strlen(name), 1)
-#define INI_ORIG_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), true))
-
 #define REGISTER_INI_ENTRIES() zend_register_ini_entries_ex(ini_entries, module_number, type)
 #define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries_ex(module_number, type)
 #define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module)
diff --git a/Zend/zend_multibyte.c b/Zend/zend_multibyte.c
index f61ed79fd1f7a..fc130162f0837 100644
--- a/Zend/zend_multibyte.c
+++ b/Zend/zend_multibyte.c
@@ -114,8 +114,8 @@ ZEND_API zend_result zend_multibyte_set_functions(const zend_multibyte_functions
 	 * populated, we need to reinitialize script_encoding here.
 	 */
 	{
-		const char *value = zend_ini_string("zend.script_encoding", sizeof("zend.script_encoding") - 1, 0);
-		zend_multibyte_set_script_encoding_by_string(value, strlen(value));
+		const zend_string *value = zend_ini_str_literal("zend.script_encoding");
+		zend_multibyte_set_script_encoding_by_string(ZSTR_VAL(value), ZSTR_LEN(value));
 	}
 	return SUCCESS;
 }
diff --git a/ext/com_dotnet/com_dotnet.c b/ext/com_dotnet/com_dotnet.c
index 7e03887d01f5f..e4ab984858312 100644
--- a/ext/com_dotnet/com_dotnet.c
+++ b/ext/com_dotnet/com_dotnet.c
@@ -139,7 +139,7 @@ static HRESULT dotnet_bind_runtime(LPVOID FAR *ppv)
 		return S_FALSE;
 	}
 
-	const zend_string *version = zend_ini_str(ZEND_STRL("com.dotnet_version"), false);
+	const zend_string *version = zend_ini_str_literal("com.dotnet_version");
 	if (version == NULL || ZSTR_LEN(version) == 0) {
 		oleversion = NULL;
 	} else {
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index e33644a607d97..a5c485d48c1df 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -1112,9 +1112,9 @@ static void _php_curl_set_default_options(php_curl *ch)
 	curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120L);
 	curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20L); /* prevent infinite redirects */
 
-	const char* cainfo = INI_STR("openssl.cafile");
+	const char* cainfo = zend_ini_string_literal("openssl.cafile");
 	if (!(cainfo && cainfo[0] != '\0')) {
-		cainfo = INI_STR("curl.cainfo");
+		cainfo = zend_ini_string_literal("curl.cainfo");
 	}
 	if (cainfo && cainfo[0] != '\0') {
 		curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index ddc7d315784b2..8208d4c3105ac 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -5480,18 +5480,18 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, bool calc_s
 	ZEND_PARSE_PARAMETERS_END();
 
 	if (latitude_is_null) {
-		latitude = INI_FLT("date.default_latitude");
+		latitude = zend_ini_double_literal("date.default_latitude");
 	}
 
 	if (longitude_is_null) {
-		longitude = INI_FLT("date.default_longitude");
+		longitude = zend_ini_double_literal("date.default_longitude");
 	}
 
 	if (zenith_is_null) {
 		if (calc_sunset) {
-			zenith = INI_FLT("date.sunset_zenith");
+			zenith = zend_ini_double_literal("date.sunset_zenith");
 		} else {
-			zenith = INI_FLT("date.sunrise_zenith");
+			zenith = zend_ini_double_literal("date.sunrise_zenith");
 		}
 	}
 
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 81f442f333485..a5aa27db693d5 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -1599,7 +1599,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
 
 #ifdef HAVE_GD_JPG
 			case PHP_GDIMG_TYPE_JPG:
-				ignore_warning = INI_INT("gd.jpeg_ignore_warning");
+				ignore_warning = zend_ini_bool_literal("gd.jpeg_ignore_warning");
 				im = gdImageCreateFromJpegEx(fp, ignore_warning);
 			break;
 #endif
diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c
index aeba4bb0beb6c..d7c9f36f4a42a 100644
--- a/ext/openssl/openssl_backend_common.c
+++ b/ext/openssl/openssl_backend_common.c
@@ -504,10 +504,8 @@ void php_openssl_set_cert_locations(zval *return_value)
 	add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env());
 	add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir());
 	add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area());
-	add_assoc_str(return_value, "ini_cafile",
-		zend_string_copy(zend_ini_str(ZEND_STRL("openssl.cafile"), false)));
-	add_assoc_str(return_value, "ini_capath",
-		zend_string_copy(zend_ini_str(ZEND_STRL("openssl.capath"), false)));
+	add_assoc_str(return_value, "ini_cafile", zend_string_copy(zend_ini_str_literal("openssl.cafile")));
+	add_assoc_str(return_value, "ini_capath", zend_string_copy(zend_ini_str_literal("openssl.capath")));
 }
 
 X509 *php_openssl_x509_from_str(
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index c6e711361a2fc..3f19857edf635 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -888,7 +888,7 @@ static zend_result php_openssl_enable_peer_verification(SSL_CTX *ctx, php_stream
 	GET_VER_OPT_STRING("capath", capath);
 
 	if (cafile == NULL) {
-		const zend_string *cafile_str = zend_ini_str(ZEND_STRL("openssl.cafile"), false);
+		const zend_string *cafile_str = zend_ini_str_literal("openssl.cafile");
 		cafile = ZSTR_LEN(cafile_str) ? ZSTR_VAL(cafile_str) : NULL;
 	} else if (!sslsock->is_client) {
 		/* Servers need to load and assign CA names from the cafile */
@@ -902,7 +902,7 @@ static zend_result php_openssl_enable_peer_verification(SSL_CTX *ctx, php_stream
 	}
 
 	if (capath == NULL) {
-		const zend_string *capath_str = zend_ini_str(ZEND_STRL("openssl.capath"), false);
+		const zend_string *capath_str = zend_ini_str_literal("openssl.capath");
 		capath = ZSTR_LEN(capath_str) ? ZSTR_VAL(capath_str) : NULL;
 	}
 
diff --git a/ext/session/session.c b/ext/session/session.c
index 02977d8d6115c..0bcef78ec42d0 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1637,7 +1637,7 @@ PHPAPI zend_result php_session_start(void)
 			break;
 
 		case php_session_disabled: {
-			const char *value = zend_ini_string(ZEND_STRL("session.save_handler"), false);
+			const char *value = zend_ini_string_literal("session.save_handler");
 			if (!PS(mod) && value) {
 				PS(mod) = _php_find_ps_module(value);
 				if (!PS(mod)) {
@@ -1645,7 +1645,7 @@ PHPAPI zend_result php_session_start(void)
 					return FAILURE;
 				}
 			}
-			value = zend_ini_string(ZEND_STRL("session.serialize_handler"), false);
+			value = zend_ini_string_literal("session.serialize_handler");
 			if (!PS(serializer) && value) {
 				PS(serializer) = _php_find_ps_serializer(value);
 				if (!PS(serializer)) {
@@ -2768,14 +2768,14 @@ static zend_result php_rinit_session(bool auto_start)
 
 	PS(mod) = NULL;
 	{
-		const char *value = zend_ini_string(ZEND_STRL("session.save_handler"), false);
+		const char *value = zend_ini_string_literal("session.save_handler");
 		if (value) {
 			PS(mod) = _php_find_ps_module(value);
 		}
 	}
 
 	if (PS(serializer) == NULL) {
-		const char *value = zend_ini_string(ZEND_STRL("session.serialize_handler"), false);
+		const char *value = zend_ini_string_literal("session.serialize_handler");
 		if (value) {
 			PS(serializer) = _php_find_ps_serializer(value);
 		}
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 6c850a27cf0f7..460e1dc84aafa 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -1665,7 +1665,7 @@ PHP_METHOD(SoapServer, handle)
 			sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
 		}
 
-		if (INI_INT("zlib.output_compression")) {
+		if (zend_ini_long_literal("zlib.output_compression")) {
 			sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
 		} else {
 			snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
@@ -1827,7 +1827,7 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade
 	if (use_http_error_status) {
 		sapi_add_header("HTTP/1.1 500 Internal Server Error", sizeof("HTTP/1.1 500 Internal Server Error")-1, 1);
 	}
-	if (INI_INT("zlib.output_compression")) {
+	if (zend_ini_long_literal("zlib.output_compression")) {
 		sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
 	} else {
 		snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 4bfcf3d77ead7..e73d6e5a1cc9e 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -1717,11 +1717,11 @@ PHPAPI bool append_user_shutdown_function(php_shutdown_function_entry *shutdown_
 
 ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
 {
-	syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment");
-	syntax_highlighter_ini->highlight_default = INI_STR("highlight.default");
-	syntax_highlighter_ini->highlight_html    = INI_STR("highlight.html");
-	syntax_highlighter_ini->highlight_keyword = INI_STR("highlight.keyword");
-	syntax_highlighter_ini->highlight_string  = INI_STR("highlight.string");
+	syntax_highlighter_ini->highlight_comment = zend_ini_string_literal("highlight.comment");
+	syntax_highlighter_ini->highlight_default = zend_ini_string_literal("highlight.default");
+	syntax_highlighter_ini->highlight_html    = zend_ini_string_literal("highlight.html");
+	syntax_highlighter_ini->highlight_keyword = zend_ini_string_literal("highlight.keyword");
+	syntax_highlighter_ini->highlight_string  = zend_ini_string_literal("highlight.string");
 }
 /* }}} */
 
@@ -2026,7 +2026,7 @@ PHP_FUNCTION(set_include_path)
 		Z_PARAM_PATH_STR(new_value)
 	ZEND_PARSE_PARAMETERS_END();
 
-	zend_string *old_value = zend_ini_str("include_path", sizeof("include_path") - 1, false);
+	zend_string *old_value = zend_ini_str_literal("include_path");
 	/* copy to return here, because alter might free it! */
 	if (old_value) {
 		RETVAL_STR_COPY(old_value);
@@ -2049,7 +2049,7 @@ PHP_FUNCTION(get_include_path)
 {
 	ZEND_PARSE_PARAMETERS_NONE();
 
-	zend_string *str = zend_ini_str("include_path", sizeof("include_path") - 1, 0);
+	zend_string *str = zend_ini_str_literal("include_path");
 
 	if (str == NULL) {
 		RETURN_FALSE;
diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c
index 1a49d1c3eab8e..ec9e3a59e4b85 100644
--- a/ext/standard/browscap.c
+++ b/ext/standard/browscap.c
@@ -337,7 +337,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
 					) {
 						zend_error(E_CORE_ERROR, "Invalid browscap ini file: "
 							"'Parent' value cannot be same as the section name: %s "
-							"(in file %s)", ZSTR_VAL(ctx->current_section_name), INI_STR("browscap"));
+							"(in file %s)", ZSTR_VAL(ctx->current_section_name), zend_ini_string_literal("browscap"));
 						return;
 					}
 
@@ -499,7 +499,7 @@ PHP_INI_MH(OnChangeBrowscap)
 
 PHP_MINIT_FUNCTION(browscap) /* {{{ */
 {
-	const char *browscap = INI_STR("browscap");
+	const char *browscap = zend_ini_string_literal("browscap");
 
 #ifdef ZTS
 	ts_allocate_id(&browscap_globals_id, sizeof(browser_data), (ts_allocate_ctor) browscap_globals_ctor, NULL);
diff --git a/ext/standard/dl.c b/ext/standard/dl.c
index d69a1d3d48dff..209b0c1d3b01c 100644
--- a/ext/standard/dl.c
+++ b/ext/standard/dl.c
@@ -118,7 +118,7 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
 	char *err1, *err2;
 
 	if (type == MODULE_PERSISTENT) {
-		extension_dir = INI_STR("extension_dir");
+		extension_dir = zend_ini_string_literal("extension_dir");
 	} else {
 		extension_dir = PG(extension_dir);
 	}
diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 1eb1b2cee0758..f12e0c8940904 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -336,7 +336,7 @@ PHP_FUNCTION(mail)
 		subject_r = subject;
 	}
 
-	zend_string *force_extra_parameters = zend_ini_str_ex("mail.force_extra_parameters", strlen("mail.force_extra_parameters"), false, NULL);
+	zend_string *force_extra_parameters = zend_ini_str_literal("mail.force_extra_parameters");
 	if (force_extra_parameters) {
 		extra_cmd = php_escape_shell_cmd(force_extra_parameters);
 	} else if (extra_cmd) {
@@ -437,9 +437,9 @@ static int php_mail_detect_multiple_crlf(const char *hdr) {
 PHPAPI bool php_mail(const char *to, const char *subject, const char *message, const char *headers, const zend_string *extra_cmd)
 {
 	FILE *sendmail;
-	const char *sendmail_path = INI_STR("sendmail_path");
+	const char *sendmail_path = zend_ini_string_literal("sendmail_path");
 	char *sendmail_cmd = NULL;
-	const zend_string *mail_log = zend_ini_str(ZEND_STRL("mail.log"), false);
+	const zend_string *mail_log = zend_ini_str_literal("mail.log");
 	const char *hdr = headers;
 	char *ahdr = NULL;
 #if PHP_SIGCHILD
@@ -536,7 +536,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 		char *tsm_errmsg = NULL;
 
 		/* handle old style win smtp sending */
-		if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message) == FAILURE) {
+		if (TSendMail(zend_ini_string_literal("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message) == FAILURE) {
 			if (tsm_errmsg) {
 				php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg);
 				efree(tsm_errmsg);
@@ -701,7 +701,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 /* {{{ PHP_MINFO_FUNCTION */
 PHP_MINFO_FUNCTION(mail)
 {
-	const char *sendmail_path = INI_STR("sendmail_path");
+	const char *sendmail_path = zend_ini_string_literal("sendmail_path");
 
 #ifdef PHP_WIN32
 	if (!sendmail_path) {
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 7cab83fb8900a..4a1245491f947 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1278,7 +1278,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
 	} else {
 		int_value = (int) zend_ini_parse_quantity_warn(new_value, entry->name);
 	}
-	const zend_string *ini_value = zend_ini_str(ZEND_STRL("output_handler"), false);
+	const zend_string *ini_value = zend_ini_str_literal("output_handler");
 
 	if (ini_value && ZSTR_LEN(ini_value) && int_value) {
 		php_error_docref("ref.outcontrol", E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
diff --git a/main/main.c b/main/main.c
index 739e8e2e00e6c..34f3cd8eb2b85 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1471,8 +1471,8 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c
 			if (PG(xmlrpc_errors)) {
 				php_printf("faultCode" ZEND_LONG_FMT "faultString%s:%s in %s on line %" PRIu32 "%s%s", PG(xmlrpc_error_number), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno, ZSTR_LEN(backtrace) ? "\nStack trace:\n" : "", ZSTR_VAL(backtrace));
 			} else {
-				const char *prepend_string = INI_STR("error_prepend_string");
-				const char *append_string = INI_STR("error_append_string");
+				const char *prepend_string = zend_ini_string_literal("error_prepend_string");
+				const char *append_string = zend_ini_string_literal("error_append_string");
 
 				if (PG(html_errors)) {
 					if (type == E_ERROR || type == E_PARSE) {
@@ -2374,7 +2374,7 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi
 	}
 
 	/* disable certain functions as requested by php.ini */
-	zend_disable_functions(INI_STR("disable_functions"));
+	zend_disable_functions(zend_ini_string_literal("disable_functions"));
 
 	/* make core report what it should */
 	if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
@@ -2638,7 +2638,7 @@ PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval)
 #ifdef PHP_WIN32
 			zend_unset_timeout();
 #endif
-			zend_set_timeout(INI_INT("max_execution_time"), 0);
+			zend_set_timeout(zend_ini_long_literal("max_execution_time"), false);
 		}
 
 		if (prepend_file_p && result) {
diff --git a/main/php_ini.c b/main/php_ini.c
index 800191285b87e..4bac70e88778f 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -334,7 +334,7 @@ static void php_load_zend_extension_cb(void *arg)
 	} else {
 		DL_HANDLE handle;
 		char *libpath;
-		const char *extension_dir = INI_STR("extension_dir");
+		const char *extension_dir = zend_ini_string_literal("extension_dir");
 		int slash_suffix = 0;
 		char *err1, *err2;
 
diff --git a/main/rfc1867.c b/main/rfc1867.c
index f6ffb6fabc7f1..161a0e4e487f5 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -665,8 +665,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
 	zend_llist header;
 	void *event_extra_data = NULL;
 	unsigned int llen = 0;
-	zend_long upload_cnt = REQUEST_PARSE_BODY_OPTION_GET(max_file_uploads, INI_INT("max_file_uploads"));
-	zend_long body_parts_cnt = REQUEST_PARSE_BODY_OPTION_GET(max_multipart_body_parts, INI_INT("max_multipart_body_parts"));
+	zend_long upload_cnt = REQUEST_PARSE_BODY_OPTION_GET(max_file_uploads, zend_ini_long_literal("max_file_uploads"));
+	zend_long body_parts_cnt = REQUEST_PARSE_BODY_OPTION_GET(max_multipart_body_parts, zend_ini_long_literal("max_multipart_body_parts"));
 	zend_long post_max_size = REQUEST_PARSE_BODY_OPTION_GET(post_max_size, SG(post_max_size));
 	zend_long max_input_vars = REQUEST_PARSE_BODY_OPTION_GET(max_input_vars, PG(max_input_vars));
 	zend_long upload_max_filesize = REQUEST_PARSE_BODY_OPTION_GET(upload_max_filesize, PG(upload_max_filesize));
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index ca5fff6ee5908..fb91cc9a840e1 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -1190,7 +1190,7 @@ static void add_zendext_info(zend_extension *ext) /* {{{ */ {
 #ifdef HAVE_LIBDL
 PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, const char **name) /* {{{ */ {
 	DL_HANDLE handle;
-	zend_string *extension_dir = zend_ini_str(ZEND_STRL("extension_dir"), false);
+	zend_string *extension_dir = zend_ini_str_literal("extension_dir");
 
 	if (strchr(*path, '/') != NULL || strchr(*path, DEFAULT_SLASH) != NULL) {
 		/* path is fine */
diff --git a/win32/sendmail.c b/win32/sendmail.c
index f267d1fae85ab..939106f31b00e 100644
--- a/win32/sendmail.c
+++ b/win32/sendmail.c
@@ -216,8 +216,8 @@ PHPAPI int TSendMail(const char *host, int *error, char **error_message,
 	}
 
 	/* Fall back to sendmail_from php.ini setting */
-	if (INI_STR("sendmail_from")) {
-		RPath = estrdup(INI_STR("sendmail_from"));
+	if (zend_ini_string_literal("sendmail_from")) {
+		RPath = estrdup(zend_ini_string_literal("sendmail_from"));
 	} else if (headers_lc) {
 		int found = 0;
 		const char *lookup = ZSTR_VAL(headers_lc);
@@ -276,7 +276,7 @@ PHPAPI int TSendMail(const char *host, int *error, char **error_message,
 		snprintf(*error_message, HOST_NAME_LEN + 128,
 			"Failed to connect to mailserver at \"%s\" port " ZEND_ULONG_FMT ", verify your \"SMTP\" "
 			"and \"smtp_port\" setting in php.ini or use ini_set()",
-			PW32G(mail_host), !INI_INT("smtp_port") ? 25 : INI_INT("smtp_port"));
+			PW32G(mail_host), !zend_ini_long_literal("smtp_port") ? 25 : zend_ini_long_literal("smtp_port"));
 		return FAILURE;
 	} else {
 		ret = SendText(RPath, Subject, mailTo, data, headers_trim, headers_lc, error_message);
@@ -789,7 +789,7 @@ return 0;
 	}
 	*/
 
-	portnum = (short) INI_INT("smtp_port");
+	portnum = (short) zend_ini_long_literal("smtp_port");
 	if (!portnum) {
 		portnum = 25;
 	}

From ccecfe0c72914c9ff99f8484fb2f7b7ae5d5ce4c Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 13:27:32 +0000
Subject: [PATCH 08/13] Remove INI_ORIG_* APIs as they are unused

A sourcegraph search shows 0 results other than for the buggy BOOL one in ext/tidy
---
 Zend/zend_ini.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index d60b3425dcf0e..d2419bb160fda 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -101,11 +101,6 @@ ZEND_API bool zend_ini_parse_bool(const zend_string *str);
 #define zend_ini_str_literal(name) zend_ini_str((name), sizeof("" name) - 1, false)
 #define zend_ini_string_literal(name) zend_ini_string((name), sizeof("" name) - 1, false)
 
-#define INI_ORIG_INT(name)	zend_ini_long((name), strlen(name), 1)
-#define INI_ORIG_FLT(name)	zend_ini_double((name), strlen(name), 1)
-#define INI_ORIG_STR(name)	zend_ini_string((name), strlen(name), 1)
-#define INI_ORIG_BOOL(name) zend_ini_parse_bool(zend_ini_str((name), strlen(name), true))
-
 /**
  * Parses an ini quantity
  *

From cb3a8be4482a2ea5e6e1b254c6d5464c9352962d Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 13:32:07 +0000
Subject: [PATCH 09/13] Address review comments

---
 ext/standard/mail.c         | 6 +++---
 ext/zlib/zlib.c             | 2 +-
 sapi/phpdbg/phpdbg_prompt.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index f12e0c8940904..72cc5aea997af 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -438,7 +438,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 {
 	FILE *sendmail;
 	const char *sendmail_path = zend_ini_string_literal("sendmail_path");
-	char *sendmail_cmd = NULL;
+	const char *sendmail_cmd = NULL;
 	const zend_string *mail_log = zend_ini_str_literal("mail.log");
 	const char *hdr = headers;
 	char *ahdr = NULL;
@@ -553,7 +553,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 	if (extra_cmd != NULL) {
 		spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, ZSTR_VAL(extra_cmd));
 	} else {
-		sendmail_cmd = (char*)sendmail_path;
+		sendmail_cmd = sendmail_path;
 	}
 
 #if PHP_SIGCHILD
@@ -576,7 +576,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 	sendmail = popen(sendmail_cmd, "w");
 #endif
 	if (extra_cmd != NULL) {
-		efree (sendmail_cmd);
+		efree((char*)sendmail_cmd);
 	}
 
 	if (sendmail) {
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 4a1245491f947..065b0f4eedbe4 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1280,7 +1280,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
 	}
 	const zend_string *ini_value = zend_ini_str_literal("output_handler");
 
-	if (ini_value && ZSTR_LEN(ini_value) && int_value) {
+	if (ini_value && ZSTR_LEN(ini_value) > 0 && int_value) {
 		php_error_docref("ref.outcontrol", E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
 		return FAILURE;
 	}
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index fb91cc9a840e1..db7a9c7cf9f5a 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -1194,9 +1194,9 @@ PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, const char *
 
 	if (strchr(*path, '/') != NULL || strchr(*path, DEFAULT_SLASH) != NULL) {
 		/* path is fine */
-	} else if (extension_dir && ZSTR_LEN(extension_dir)) {
+	} else if (extension_dir && ZSTR_LEN(extension_dir) > 0) {
 		char *libpath;
-		if (IS_SLASH(ZSTR_VAL(extension_dir)[ZSTR_LEN(extension_dir-1)])) {
+		if (IS_SLASH(ZSTR_VAL(extension_dir)[ZSTR_LEN(extension_dir)-1])) {
 			spprintf(&libpath, 0, "%s%s", ZSTR_VAL(extension_dir), *path); /* SAFE */
 		} else {
 			spprintf(&libpath, 0, "%s%c%s", ZSTR_VAL(extension_dir), DEFAULT_SLASH, *path); /* SAFE */

From 7f382d2a0b24da2dc6795f476c994c77e44d48b2 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 13:33:20 +0000
Subject: [PATCH 10/13] UPGRADING.INTERNALS

---
 UPGRADING.INTERNALS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index fc672ac54a821..840470eecfb6e 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -74,6 +74,14 @@ PHP 8.6 INTERNALS UPGRADE NOTES
     longer is a pointer, but a directly embedded HashTable struct.
   . Added a C23_ENUM() helper macro to define forward-compatible fixed-size
     enums.
+  . The INI_STR(), INI_INT(), INI_FLT(), and INI_BOOL() macros have been
+    removed. Instead new zend_ini_{bool|long|double|str|string}_literal()
+    macros have been added. This fixes an internal naming inconsistency as
+    "str" usually means zend_string*, and "string" means char*.
+    However INI_STR() returned a char*
+  . The INI_ORIG_{INT|STR|FLT|BOOL}() macros have been removed as they are
+    unused. If this behaviour is required fall back to the zend_ini_*
+    functions.
 
 ========================
 2. Build system changes

From fb66db31701ce439bb5dd2e3a188d8bd01f688d6 Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 13:49:02 +0000
Subject: [PATCH 11/13] ext/mbstring: use new ini API and remove unnecessary
 casts

---
 ext/mbstring/mbstring.c | 56 ++++++++++++++++++-----------------------
 1 file changed, 25 insertions(+), 31 deletions(-)

diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 95b624ef1d2d2..c5987f3c9e7a4 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -1216,17 +1216,17 @@ PHP_FUNCTION(mb_language)
 	ZEND_PARSE_PARAMETERS_END();
 
 	if (name == NULL) {
-		RETVAL_STRING((char *)mbfl_no_language2name(MBSTRG(language)));
+		RETVAL_STRING(mbfl_no_language2name(MBSTRG(language)));
 	} else {
-		zend_string *ini_name = ZSTR_INIT_LITERAL("mbstring.language", 0);
+		zend_string *ini_name = ZSTR_INIT_LITERAL("mbstring.language", false);
 		if (FAILURE == zend_alter_ini_entry(ini_name, name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME)) {
 			zend_argument_value_error(1, "must be a valid language, \"%s\" given", ZSTR_VAL(name));
-			zend_string_release_ex(ini_name, 0);
+			zend_string_release_ex(ini_name, false);
 			RETURN_THROWS();
 		}
 		// TODO Make return void
 		RETVAL_TRUE;
-		zend_string_release_ex(ini_name, 0);
+		zend_string_release_ex(ini_name, false);
 	}
 }
 /* }}} */
@@ -1509,7 +1509,7 @@ PHP_FUNCTION(mb_preferred_mime_name)
 		php_error_docref(NULL, E_WARNING, "No MIME preferred name corresponding to \"%s\"", name);
 		RETVAL_FALSE;
 	} else {
-		RETVAL_STRING((char *)preferred_name);
+		RETVAL_STRING(preferred_name);
 	}
 }
 /* }}} */
@@ -3517,7 +3517,7 @@ PHP_FUNCTION(mb_detect_encoding)
 		RETURN_FALSE;
 	}
 
-	RETVAL_STRING((char *)ret->name);
+	RETVAL_STRING(ret->name);
 }
 /* }}} */
 
@@ -3563,7 +3563,7 @@ PHP_FUNCTION(mb_encoding_aliases)
 	array_init(return_value);
 	if (encoding->aliases != NULL) {
 		for (const char **alias = encoding->aliases; *alias; ++alias) {
-			add_next_index_string(return_value, (char *)*alias);
+			add_next_index_string(return_value, *alias);
 		}
 	}
 }
@@ -4768,7 +4768,7 @@ PHP_FUNCTION(mb_send_mail)
 
 	str_headers = smart_str_extract(&str);
 
-	zend_string *force_extra_parameters = zend_ini_str_ex("mail.force_extra_parameters", strlen("mail.force_extra_parameters"), false, NULL);
+	zend_string *force_extra_parameters = zend_ini_str_literal("mail.force_extra_parameters");
 	if (force_extra_parameters) {
 		extra_cmd = php_escape_shell_cmd(force_extra_parameters);
 	} else if (extra_cmd) {
@@ -4804,7 +4804,7 @@ PHP_FUNCTION(mb_get_info)
 {
 	zend_string *type = NULL;
 	size_t n;
-	char *name;
+	const char *name;
 	zval row;
 	const mbfl_encoding **entry;
 	const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
@@ -4819,26 +4819,26 @@ PHP_FUNCTION(mb_get_info)
 	if (!type || zend_string_equals_literal_ci(type, "all")) {
 		array_init(return_value);
 		if (MBSTRG(current_internal_encoding)) {
-			add_assoc_string(return_value, "internal_encoding", (char *)MBSTRG(current_internal_encoding)->name);
+			add_assoc_string(return_value, "internal_encoding", MBSTRG(current_internal_encoding)->name);
 		}
 		if (MBSTRG(http_input_identify)) {
-			add_assoc_string(return_value, "http_input", (char *)MBSTRG(http_input_identify)->name);
+			add_assoc_string(return_value, "http_input", MBSTRG(http_input_identify)->name);
 		}
 		if (MBSTRG(current_http_output_encoding)) {
-			add_assoc_string(return_value, "http_output", (char *)MBSTRG(current_http_output_encoding)->name);
+			add_assoc_string(return_value, "http_output", MBSTRG(current_http_output_encoding)->name);
 		}
 
 		add_assoc_str(return_value, "http_output_conv_mimetypes",
-			zend_ini_str("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes") - 1, 0)
+			zend_string_copy(zend_ini_str_literal("mbstring.http_output_conv_mimetypes"))
 		);
 
-		name = (char *)mbfl_no_encoding2name(lang->mail_charset);
+		name = mbfl_no_encoding2name(lang->mail_charset);
 		add_assoc_string(return_value, "mail_charset", name);
 
-		name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding);
+		name = mbfl_no_encoding2name(lang->mail_header_encoding);
 		add_assoc_string(return_value, "mail_header_encoding", name);
 
-		name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding);
+		name = mbfl_no_encoding2name(lang->mail_body_encoding);
 		add_assoc_string(return_value, "mail_body_encoding", name);
 
 		add_assoc_long(return_value, "illegal_chars", MBSTRG(illegalchars));
@@ -4849,7 +4849,7 @@ PHP_FUNCTION(mb_get_info)
 			add_assoc_string(return_value, "encoding_translation", "Off");
 		}
 
-		name = (char *)mbfl_no_language2name(MBSTRG(language));
+		name = mbfl_no_language2name(MBSTRG(language));
 		add_assoc_string(return_value, "language", name);
 
 		// TODO Seems to always have one entry at least?
@@ -4880,31 +4880,25 @@ PHP_FUNCTION(mb_get_info)
 		}
 	} else if (zend_string_equals_literal_ci(type, "internal_encoding")) {
 		ZEND_ASSERT(MBSTRG(current_internal_encoding));
-		RETURN_STRING((char *)MBSTRG(current_internal_encoding)->name);
+		RETURN_STRING(MBSTRG(current_internal_encoding)->name);
 	} else if (zend_string_equals_literal_ci(type, "http_input")) {
 		if (MBSTRG(http_input_identify)) {
-			RETURN_STRING((char *)MBSTRG(http_input_identify)->name);
+			RETURN_STRING(MBSTRG(http_input_identify)->name);
 		}
 		RETURN_NULL();
 	} else if (zend_string_equals_literal_ci(type, "http_output")) {
 		ZEND_ASSERT(MBSTRG(current_http_output_encoding));
-		RETURN_STRING((char *)MBSTRG(current_http_output_encoding)->name);
+		RETURN_STRING(MBSTRG(current_http_output_encoding)->name);
 	} else if (zend_string_equals_literal_ci(type, "http_output_conv_mimetypes")) {
-		RETURN_STR(
-			zend_ini_str(
-				"mbstring.http_output_conv_mimetypes",
-				sizeof("mbstring.http_output_conv_mimetypes") - 1,
-				false
-			)
-		);
+		RETURN_STR_COPY(zend_ini_str_literal("mbstring.http_output_conv_mimetypes"));
 	} else if (zend_string_equals_literal_ci(type, "mail_charset")) {
-		name = (char *)mbfl_no_encoding2name(lang->mail_charset);
+		name = mbfl_no_encoding2name(lang->mail_charset);
 		RETURN_STRING(name);
 	} else if (zend_string_equals_literal_ci(type, "mail_header_encoding")) {
-		name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding);
+		name = mbfl_no_encoding2name(lang->mail_header_encoding);
 		RETURN_STRING(name);
 	} else if (zend_string_equals_literal_ci(type, "mail_body_encoding")) {
-		name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding);
+		name = mbfl_no_encoding2name(lang->mail_body_encoding);
 		RETURN_STRING(name);
 	} else if (zend_string_equals_literal_ci(type, "illegal_chars")) {
 		RETURN_LONG(MBSTRG(illegalchars));
@@ -4915,7 +4909,7 @@ PHP_FUNCTION(mb_get_info)
 			RETURN_STRING("Off");
 		}
 	} else if (zend_string_equals_literal_ci(type, "language")) {
-		name = (char *)mbfl_no_language2name(MBSTRG(language));
+		name = mbfl_no_language2name(MBSTRG(language));
 		RETURN_STRING(name);
 	} else if (zend_string_equals_literal_ci(type, "detect_order")) {
 		// TODO Seems to always have one entry at least?

From a2564f7c0a8481c6d638a7afaa53a0520eaba37f Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 14:02:14 +0000
Subject: [PATCH 12/13] revert marking sendmail_cmd as const

It is used as a target for snprintf, so must be mutable
---
 ext/standard/mail.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 72cc5aea997af..dbb4e54e00392 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -438,7 +438,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 {
 	FILE *sendmail;
 	const char *sendmail_path = zend_ini_string_literal("sendmail_path");
-	const char *sendmail_cmd = NULL;
+	char *sendmail_cmd = NULL;
 	const zend_string *mail_log = zend_ini_str_literal("mail.log");
 	const char *hdr = headers;
 	char *ahdr = NULL;
@@ -553,7 +553,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 	if (extra_cmd != NULL) {
 		spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, ZSTR_VAL(extra_cmd));
 	} else {
-		sendmail_cmd = sendmail_path;
+		sendmail_cmd = (char*)sendmail_path;
 	}
 
 #if PHP_SIGCHILD
@@ -576,7 +576,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
 	sendmail = popen(sendmail_cmd, "w");
 #endif
 	if (extra_cmd != NULL) {
-		efree((char*)sendmail_cmd);
+		efree(sendmail_cmd);
 	}
 
 	if (sendmail) {

From dfa590f326b0ad998b04b1887c8e2814f37a916b Mon Sep 17 00:00:00 2001
From: Gina Peter Banyard 
Date: Mon, 23 Feb 2026 15:44:46 +0000
Subject: [PATCH 13/13] Add length check, as it turns out the non _ex version
 returns an empty string rather than NULL in certain cases

---
 ext/standard/mail.c                      | 2 +-
 ext/standard/tests/mail/mail_basic2.phpt | 7 +++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index dbb4e54e00392..c909c0ed55dd7 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -337,7 +337,7 @@ PHP_FUNCTION(mail)
 	}
 
 	zend_string *force_extra_parameters = zend_ini_str_literal("mail.force_extra_parameters");
-	if (force_extra_parameters) {
+	if (force_extra_parameters && ZSTR_LEN(force_extra_parameters) > 0) {
 		extra_cmd = php_escape_shell_cmd(force_extra_parameters);
 	} else if (extra_cmd) {
 		extra_cmd = php_escape_shell_cmd(extra_cmd);
diff --git a/ext/standard/tests/mail/mail_basic2.phpt b/ext/standard/tests/mail/mail_basic2.phpt
index 44d8d86310b01..96a5a4a10a113 100644
--- a/ext/standard/tests/mail/mail_basic2.phpt
+++ b/ext/standard/tests/mail/mail_basic2.phpt
@@ -20,14 +20,17 @@ $message = 'A Message';
 $additional_headers = 'KHeaders';
 $additional_parameters = "-n";
 $outFile = "/tmp/php_test_mailBasic2.out";
-@unlink($outFile);
 
 echo "-- extra parameters --\n";
 // Calling mail() with all possible arguments
 var_dump( mail($to, $subject, $message, $additional_headers, $additional_parameters) );
 
 echo file_get_contents($outFile);
-unlink($outFile);
+
+?>
+--CLEAN--
+
 --EXPECTF--
 *** Testing mail() : basic functionality ***