From 38c3e0e6d48edd96efb9c93be48c7e5f775a1009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Lazd=C4=81ns?= Date: Tue, 4 Mar 2025 20:25:10 +0200 Subject: [PATCH 01/12] Replace bool with int --- interbase.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interbase.c b/interbase.c index 3d93ac0..a3df1dd 100644 --- a/interbase.c +++ b/interbase.c @@ -711,12 +711,12 @@ static PHP_INI_DISP(php_ibase_password_displayer_cb) PUTS(" | "); \ } \ PUTS(str); \ - has_puts = true; \ + has_puts = 1; \ } while (0) static PHP_INI_DISP(php_ibase_trans_displayer) { - bool has_puts = false; + int has_puts = 0; char *value; if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) { From 78f239c2195d977a0310b681cab464b43f444897 Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Sat, 11 Oct 2025 02:09:04 +0300 Subject: [PATCH 02/12] Skip INT128 test when FB < 4.0 --- tests/datatype_int128.phpt | 1 + tests/interbase.inc | 17 +++++++++++++++++ tests/skipif.inc | 3 +-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/datatype_int128.phpt b/tests/datatype_int128.phpt index 0cbdda5..47e3bf2 100644 --- a/tests/datatype_int128.phpt +++ b/tests/datatype_int128.phpt @@ -3,6 +3,7 @@ Check for data type INT128 (Firebird 4.0 or above) --SKIPIF-- --FILE-- From 56827a49b987d8f09cf81f6e26a2baf6a6490b99 Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Sat, 11 Oct 2025 10:46:41 +0300 Subject: [PATCH 03/12] Whitespaces --- tests/datatype_int128.phpt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/datatype_int128.phpt b/tests/datatype_int128.phpt index 47e3bf2..b97f6ee 100644 --- a/tests/datatype_int128.phpt +++ b/tests/datatype_int128.phpt @@ -8,19 +8,19 @@ if(get_fb_version() < 4.0)print "skip FB < 4.0"; --FILE-- Date: Sat, 11 Oct 2025 10:47:52 +0300 Subject: [PATCH 04/12] Captitalize SQL --- tests/datatype_int128.phpt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/datatype_int128.phpt b/tests/datatype_int128.phpt index b97f6ee..e75d03e 100644 --- a/tests/datatype_int128.phpt +++ b/tests/datatype_int128.phpt @@ -13,16 +13,16 @@ if(get_fb_version() < 4.0)print "skip FB < 4.0"; $db = ibase_connect($test_base); ibase_query( - "create table test_dt ( - v_int128 int128 not null + "CREATE TABLE TEST_DT ( + V_INT128 INT128 NOT NULL )"); ibase_commit(); - ibase_query("insert into test_dt (v_int128) values (1234)"); - ibase_query("insert into test_dt (v_int128) values (-170141183460469231731687303715884105728)"); - ibase_query("insert into test_dt (v_int128) values (170141183460469231731687303715884105727)"); + ibase_query("INSERT INTO TEST_DT (V_INT128) VALUES (1234)"); + ibase_query("INSERT INTO TEST_DT (V_INT128) VALUES (-170141183460469231731687303715884105728)"); + ibase_query("INSERT INTO TEST_DT (V_INT128) VALUES (170141183460469231731687303715884105727)"); - $sql = 'select * from test_dt'; + $sql = 'SELECT * FROM TEST_DT'; $query = ibase_query($sql); while(($row = ibase_fetch_assoc($query))) { var_dump($row); From a9e57d8468712942f9c0d53a1c4b8e410ff39b39 Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Sat, 11 Oct 2025 15:14:09 +0300 Subject: [PATCH 05/12] Fix test 'Bug #45373' (#44) --- tests/bug45373.phpt | 32 ++++++++++++++------------------ tests/skipif-php8-or-newer.inc | 2 +- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/tests/bug45373.phpt b/tests/bug45373.phpt index dcec244..8a441b1 100644 --- a/tests/bug45373.phpt +++ b/tests/bug45373.phpt @@ -5,29 +5,28 @@ Bug #45373 (php crash on query with errors in params) include("skipif.inc"); // See GitHub issue 44 // https://github.com/FirebirdSQL/php-firebird/issues/44 -include("skipif-php8-or-newer.inc"); ?> --FILE-- --EXPECTF-- @@ -47,6 +46,3 @@ array(2) { } Warning: ibase_execute(): Statement expects 2 arguments, 1 given in %s on line %d - -Warning: ibase_fetch_assoc() expects parameter 1 to be resource, bool given in %s on line %d -NULL diff --git a/tests/skipif-php8-or-newer.inc b/tests/skipif-php8-or-newer.inc index bbf5c26..e3b7a55 100644 --- a/tests/skipif-php8-or-newer.inc +++ b/tests/skipif-php8-or-newer.inc @@ -1,5 +1,5 @@ = 8) { die('skip: This test verifies behavior that can only be observed in PHP versions < 8.0'); } -?> From 009fbe478de6a478a0106065f611b3fd0a3267fa Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Sat, 11 Oct 2025 15:14:47 +0300 Subject: [PATCH 06/12] Use systems tmp folder --- tests/ibase_drop_db_001.phpt | 2 +- tests/ibase_drop_db_002.phpt | 2 +- tests/ibase_drop_db_003.phpt | 2 +- tests/ibase_drop_db_004.phpt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ibase_drop_db_001.phpt b/tests/ibase_drop_db_001.phpt index 64efeae..03f7378 100644 --- a/tests/ibase_drop_db_001.phpt +++ b/tests/ibase_drop_db_001.phpt @@ -7,7 +7,7 @@ ibase_drop_db(): Basic test require("config.inc"); -unlink($file = tempnam('/tmp',"php_ibase_test")); +unlink($file = tempnam(sys_get_temp_dir(),"php_ibase_test")); if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, diff --git a/tests/ibase_drop_db_002.phpt b/tests/ibase_drop_db_002.phpt index 34b0f41..0f1dfb4 100644 --- a/tests/ibase_drop_db_002.phpt +++ b/tests/ibase_drop_db_002.phpt @@ -10,7 +10,7 @@ include("skipif-php8-or-newer.inc"); require("config.inc"); -unlink($file = tempnam('/tmp',"php_ibase_test")); +unlink($file = tempnam(sys_get_temp_dir(),"php_ibase_test")); $db = ibase_query(IBASE_CREATE, sprintf("CREATE SCHEMA '%s' USER '%s' PASSWORD '%s' DEFAULT CHARACTER SET %s",$file, diff --git a/tests/ibase_drop_db_003.phpt b/tests/ibase_drop_db_003.phpt index 1269412..2a3ada3 100644 --- a/tests/ibase_drop_db_003.phpt +++ b/tests/ibase_drop_db_003.phpt @@ -10,7 +10,7 @@ include("skipif-php7-or-older.inc"); require("config.inc"); -unlink($file = tempnam('/tmp',"php_ibase_test")); +unlink($file = tempnam(sys_get_temp_dir(),"php_ibase_test")); if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, diff --git a/tests/ibase_drop_db_004.phpt b/tests/ibase_drop_db_004.phpt index b91202f..f355a79 100644 --- a/tests/ibase_drop_db_004.phpt +++ b/tests/ibase_drop_db_004.phpt @@ -10,7 +10,7 @@ include("skipif-php7-or-older.inc"); require("config.inc"); -unlink($file = tempnam('/tmp',"php_ibase_test")); +unlink($file = tempnam(sys_get_temp_dir(),"php_ibase_test")); if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, From 95aec4b22f294e495a0bd9276d68c4fa96285996 Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Sat, 11 Oct 2025 16:18:52 +0300 Subject: [PATCH 07/12] Re-enable test 005.phpt (#41) I will assume there are no deadlock anymore in this situation in FB5 --- tests/005.phpt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/005.phpt b/tests/005.phpt index 382ea30..4cbff64 100644 --- a/tests/005.phpt +++ b/tests/005.phpt @@ -1,16 +1,21 @@ --TEST-- InterBase: transactions --SKIPIF-- - += 5.0)print 'skip: FB >= 5.0'; +?> --FILE-- Date: Sat, 11 Oct 2025 20:26:09 +0300 Subject: [PATCH 08/12] Fix memleaks (#65) --- ibase_query.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ibase_query.c b/ibase_query.c index 3d8a46a..d8848d5 100644 --- a/ibase_query.c +++ b/ibase_query.c @@ -1901,6 +1901,10 @@ PHP_FUNCTION(ibase_free_result) } ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result); + + _php_ibase_free_xsqlda(ib_result->out_sqlda); + efree(ib_result); + zend_list_delete(Z_RES_P(result_arg)); /* From c62c583c837cfc2970ee3db8335fe750f86046bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Lazd=C4=81ns?= Date: Sun, 12 Oct 2025 03:29:15 +0300 Subject: [PATCH 09/12] Add test for #35 --- tests/issue35_001.phpt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/issue35_001.phpt diff --git a/tests/issue35_001.phpt b/tests/issue35_001.phpt new file mode 100644 index 0000000..71ab62f --- /dev/null +++ b/tests/issue35_001.phpt @@ -0,0 +1,34 @@ +--TEST-- +Issue #35: ibase_prepare() fails to find table with SQL that has double quotes on table identifiers +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +object(stdClass)#1 (2) { + ["ID"]=> + int(1) + ["CLIENT_NAME"]=> + string(9) "Some name" +} \ No newline at end of file From 60073baacde7b6bd450a9cdda29fb5628a8ce567 Mon Sep 17 00:00:00 2001 From: Martins Lazdans Date: Mon, 13 Oct 2025 09:44:28 +0300 Subject: [PATCH 10/12] Presave fb_version_str (for debugging) --- tests/interbase.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/interbase.inc b/tests/interbase.inc index 7ab610e..edfdfcb 100644 --- a/tests/interbase.inc +++ b/tests/interbase.inc @@ -32,14 +32,14 @@ function cleanup_db() function get_fb_version(): float { - global $host, $user, $password, $fb_version; + global $host, $user, $password, $fb_version, $fb_version_str; if(isset($fb_version)) return $fb_version; if($se = ibase_service_attach($host ? $host : "localhost", $user, $password)) { - $info = ibase_server_info($se, IBASE_SVC_SERVER_VERSION); - if($info === false)die("skip cannot ibase_server_info()"); - $server_version = explode(" ", $info); + $fb_version_str = ibase_server_info($se, IBASE_SVC_SERVER_VERSION); + if($fb_version_str === false)die("skip cannot ibase_server_info()"); + $server_version = explode(" ", $fb_version_str); $vers = (float)$server_version[count($server_version) - 1]; return $fb_version = $vers; } else { From 426b6752de0c87fcaf371261db1e8daa838d2513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Lazd=C4=81ns?= Date: Mon, 13 Oct 2025 21:08:14 +0300 Subject: [PATCH 11/12] Do not needlessly attach :service_mgr to an empty host (#53) Also makes internal buffers larger to match FB5 username / password lengths Also makes all arguments to ibase_service_attach() optional. These are not needed for embedded for example. --- ibase_service.c | 50 +++++++++++++++++++++++++++++++++++++------------ interbase.c | 2 +- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/ibase_service.c b/ibase_service.c index c472163..69d4ae0 100644 --- a/ibase_service.c +++ b/ibase_service.c @@ -214,34 +214,60 @@ PHP_FUNCTION(ibase_delete_user) Connect to the service manager */ PHP_FUNCTION(ibase_service_attach) { - size_t hlen, ulen, plen, spb_len; + size_t hlen = 0, ulen = 0, plen = 0; ibase_service *svm; - char buf[128], *host, *user, *pass, *loc; + char buf[350], *host, *user, *pass; + char loc[128] = "service_mgr"; isc_svc_handle handle = 0; + unsigned short p = 0; RESET_ERRMSG; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "sss", + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &host, &hlen, &user, &ulen, &pass, &plen)) { RETURN_FALSE; } - /* construct the spb, hack the service name into it as well */ - spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%s" "%s:service_mgr", - isc_spb_version, isc_spb_current_version, isc_spb_user_name, (char)ulen, - user, isc_spb_password, (char)plen, pass, host); + if (ulen > 63) { + _php_ibase_module_error("Internal error: dba_username too long"); + RETURN_FALSE; + } - if (spb_len > sizeof(buf) || spb_len == -1) { - _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%zd)", spb_len); + if (plen > 255) { + _php_ibase_module_error("Internal error: dba_password too long"); + RETURN_FALSE; + } + + // 13 = strlen(":service_mgr") + \0; + if (hlen + 13 > sizeof(loc)) { + _php_ibase_module_error("Internal error: insufficient buffer space for name of the service (%zd)", hlen + 13); RETURN_FALSE; } - spb_len -= hlen + 12; - loc = buf + spb_len; /* points to %s:service_mgr part */ + buf[p++] = isc_spb_version; + buf[p++] = isc_spb_current_version; + + if(ulen > 0){ + buf[p++] = isc_spb_user_name; + buf[p++] = (char)ulen; + memcpy(&buf[p], &user, ulen); + p += ulen; + } + + if(plen > 0){ + buf[p++] = isc_spb_password; + buf[p++] = (char)plen; + memcpy(&buf[p], &pass, plen); + p += plen; + } + + if(hlen > 0){ + slprintf(loc, sizeof(loc), "%s:service_mgr", host); + } /* attach to the service manager */ - if (isc_service_attach(IB_STATUS, 0, loc, &handle, (unsigned short)spb_len, buf)) { + if (isc_service_attach(IB_STATUS, 0, loc, &handle, p, buf)) { _php_ibase_error(); RETURN_FALSE; } diff --git a/interbase.c b/interbase.c index c21176c..67d15c7 100644 --- a/interbase.c +++ b/interbase.c @@ -256,7 +256,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3) ZEND_ARG_INFO(0, last_name) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3) +ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 0) ZEND_ARG_INFO(0, host) ZEND_ARG_INFO(0, dba_username) ZEND_ARG_INFO(0, dba_password) From 313fe8bfa89832750355ac4624c0ba5491028269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Lazd=C4=81ns?= Date: Mon, 13 Oct 2025 21:08:55 +0300 Subject: [PATCH 12/12] Add fbp_dump_buffer() utility for dumping memory (for debug) --- interbase.c | 13 +++++++++++++ php_ibase_includes.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/interbase.c b/interbase.c index 67d15c7..5df9676 100644 --- a/interbase.c +++ b/interbase.c @@ -1589,6 +1589,19 @@ PHP_FUNCTION(ibase_gen_id) RETURN_LONG((zend_long)result); } +void fbp_dump_buffer(int len, const unsigned char *buffer){ + int i; + for (i = 0; i < len; i++) { + if(buffer[i] < 31 || buffer[i] > 126) + php_printf("0x%02x ", buffer[i]); + else + php_printf("%c", buffer[i]); + } + if (i > 0) { + php_printf("\n"); + } +} + /* }}} */ #endif /* HAVE_IBASE */ diff --git a/php_ibase_includes.h b/php_ibase_includes.h index f162310..5e768f5 100644 --- a/php_ibase_includes.h +++ b/php_ibase_includes.h @@ -203,4 +203,6 @@ void php_ibase_service_minit(INIT_FUNC_ARGS); #define max(a,b) ((a)>(b)?(a):(b)) #endif +void fbp_dump_buffer(int len, const unsigned char *buffer); + #endif /* PHP_IBASE_INCLUDES_H */