From ecd9839c6a9e406b5f5cee8977579c29c389e3aa Mon Sep 17 00:00:00 2001 From: SakiTakamachi Date: Sun, 14 Jan 2024 00:30:21 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Fix=20GH13119:=20Changed=20to=20convert=20f?= =?UTF-8?q?loat=20and=20double=20values=20=E2=80=8B=E2=80=8Binto=20strings?= =?UTF-8?q?=20using=20zend=5Fgcvt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ext/pdo_firebird/firebird_statement.c | 17 +++++- ext/pdo_firebird/tests/gh10908.phpt | 12 ++--- ext/pdo_firebird/tests/gh13119.phpt | 77 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 ext/pdo_firebird/tests/gh13119.phpt diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 4ad51ab483d96..e8b71aa5165c3 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -51,6 +51,11 @@ static zend_always_inline double get_double_from_sqldata(const ISC_SCHAR *sqldat READ_AND_RETURN_USING_MEMCPY(double, sqldata); } +static zend_always_inline float get_float_from_sqldata(const ISC_SCHAR *sqldata) +{ + READ_AND_RETURN_USING_MEMCPY(float, sqldata); +} + static zend_always_inline ISC_TIMESTAMP get_isc_timestamp_from_sqldata(const ISC_SCHAR *sqldata) { READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP, sqldata); @@ -459,11 +464,19 @@ static int firebird_stmt_get_col( break; case SQL_FLOAT: /* TODO: Why is this not returned as the native type? */ - ZVAL_STR(result, zend_strpprintf(0, "%F", *(float*)var->sqldata)); + { + char f_buf[256]; + zend_gcvt((double) get_float_from_sqldata(var->sqldata), 8, '.', 'E', f_buf); + ZVAL_STRINGL_FAST(result, f_buf, strlen(f_buf)); + } break; case SQL_DOUBLE: /* TODO: Why is this not returned as the native type? */ - ZVAL_STR(result, zend_strpprintf(0, "%F", get_double_from_sqldata(var->sqldata))); + { + char d_buf[256]; + zend_gcvt(get_double_from_sqldata(var->sqldata), 16, '.', 'E', d_buf); + ZVAL_STRINGL_FAST(result, d_buf, strlen(d_buf)); + } break; #ifdef SQL_BOOLEAN case SQL_BOOLEAN: diff --git a/ext/pdo_firebird/tests/gh10908.phpt b/ext/pdo_firebird/tests/gh10908.phpt index a1e8271ffd19b..bcd3bb1e20024 100644 --- a/ext/pdo_firebird/tests/gh10908.phpt +++ b/ext/pdo_firebird/tests/gh10908.phpt @@ -79,8 +79,8 @@ Array Array ( - [DBL] => 1.000000 - [0] => 1.000000 + [DBL] => 1 + [0] => 1 ) Array @@ -103,10 +103,10 @@ Array [1] => ABC [NUM] => 12.340 [2] => 12.340 - [DBL] => 1.000000 - [3] => 1.000000 - [FLT] => 2.000000 - [4] => 2.000000 + [DBL] => 1 + [3] => 1 + [FLT] => 2 + [4] => 2 [TS] => 2023-03-24 17:39:00 [5] => 2023-03-24 17:39:00 [MYDATE] => 2023-03-24 diff --git a/ext/pdo_firebird/tests/gh13119.phpt b/ext/pdo_firebird/tests/gh13119.phpt new file mode 100644 index 0000000000000..29524e3d3bf95 --- /dev/null +++ b/ext/pdo_firebird/tests/gh13119.phpt @@ -0,0 +1,77 @@ +--TEST-- +GH-13119 (float, double value is incorrect) +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--XLEAK-- +A bug in firebird causes a memory leak when calling `isc_attach_database()`. +See https://github.com/FirebirdSQL/firebird/issues/7849 +--FILE-- +exec('CREATE TABLE gh13119 (f_val FLOAT, d_val DOUBLE PRECISION)'); + +$dbh->exec('INSERT INTO gh13119 VALUES (0.1, 0.1)'); +$dbh->exec('INSERT INTO gh13119 VALUES (0.0000000000000001, 0.0000000000000001)'); +$dbh->exec('INSERT INTO gh13119 VALUES (12.000000, 12.00000000000000)'); +$dbh->exec('INSERT INTO gh13119 VALUES (12.000001, 12.00000000000001)'); +$dbh->exec('INSERT INTO gh13119 VALUES (12.345678, 12.34567890123456)'); +$dbh->exec('INSERT INTO gh13119 VALUES (0.0000000000000000012345678, 0.000000000000000001234567890123456)'); + +$stmt = $dbh->query('select * from gh13119'); +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); +?> +--CLEAN-- +exec('DROP TABLE gh13119'); +unset($dbh); +?> +--EXPECT-- +array(6) { + [0]=> + array(2) { + ["F_VAL"]=> + string(3) "0.1" + ["D_VAL"]=> + string(3) "0.1" + } + [1]=> + array(2) { + ["F_VAL"]=> + string(7) "1.0E-16" + ["D_VAL"]=> + string(7) "1.0E-16" + } + [2]=> + array(2) { + ["F_VAL"]=> + string(2) "12" + ["D_VAL"]=> + string(2) "12" + } + [3]=> + array(2) { + ["F_VAL"]=> + string(9) "12.000001" + ["D_VAL"]=> + string(17) "12.00000000000001" + } + [4]=> + array(2) { + ["F_VAL"]=> + string(9) "12.345678" + ["D_VAL"]=> + string(17) "12.34567890123456" + } + [5]=> + array(2) { + ["F_VAL"]=> + string(13) "1.2345678E-18" + ["D_VAL"]=> + string(21) "1.234567890123456E-18" + } +} From 8740151dffc5e08d39f4897ba46ef3e6f2dacca6 Mon Sep 17 00:00:00 2001 From: SakiTakamachi Date: Sun, 14 Jan 2024 22:35:36 +0900 Subject: [PATCH 2/3] change to use `zend_strpprintf_unchecked` --- ext/pdo_firebird/firebird_statement.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index e8b71aa5165c3..225554558af64 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -464,19 +464,11 @@ static int firebird_stmt_get_col( break; case SQL_FLOAT: /* TODO: Why is this not returned as the native type? */ - { - char f_buf[256]; - zend_gcvt((double) get_float_from_sqldata(var->sqldata), 8, '.', 'E', f_buf); - ZVAL_STRINGL_FAST(result, f_buf, strlen(f_buf)); - } + ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.*H", get_float_from_sqldata(var->sqldata), 8)); break; case SQL_DOUBLE: /* TODO: Why is this not returned as the native type? */ - { - char d_buf[256]; - zend_gcvt(get_double_from_sqldata(var->sqldata), 16, '.', 'E', d_buf); - ZVAL_STRINGL_FAST(result, d_buf, strlen(d_buf)); - } + ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.*H", get_double_from_sqldata(var->sqldata), 16)); break; #ifdef SQL_BOOLEAN case SQL_BOOLEAN: From e60d7be72089dfa3c55325d1d830d9e6efd5768a Mon Sep 17 00:00:00 2001 From: SakiTakamachi Date: Mon, 15 Jan 2024 00:11:06 +0900 Subject: [PATCH 3/3] Specify numbers instead of wildcards --- ext/pdo_firebird/firebird_statement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 225554558af64..1fe894cd631df 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -464,11 +464,11 @@ static int firebird_stmt_get_col( break; case SQL_FLOAT: /* TODO: Why is this not returned as the native type? */ - ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.*H", get_float_from_sqldata(var->sqldata), 8)); + ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.8H", get_float_from_sqldata(var->sqldata))); break; case SQL_DOUBLE: /* TODO: Why is this not returned as the native type? */ - ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.*H", get_double_from_sqldata(var->sqldata), 16)); + ZVAL_STR(result, zend_strpprintf_unchecked(0, "%.16H", get_double_from_sqldata(var->sqldata))); break; #ifdef SQL_BOOLEAN case SQL_BOOLEAN: