From fd9137c00cddbb913f306238b23eef0c7ec45ab0 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 08:18:32 +0200 Subject: [PATCH 01/18] add skip slow test --- ext/pdo_dblib/tests/timeout.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/pdo_dblib/tests/timeout.phpt b/ext/pdo_dblib/tests/timeout.phpt index d65046262ed..f92a7da72f1 100644 --- a/ext/pdo_dblib/tests/timeout.phpt +++ b/ext/pdo_dblib/tests/timeout.phpt @@ -3,6 +3,7 @@ PDO_DBLIB: Set query timeouts --SKIPIF-- --FILE-- From 354a682c3830cecce0e15ecff370865857e7fcd8 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 08:21:10 +0200 Subject: [PATCH 02/18] fix test --- ext/pdo_dblib/tests/bug_45876.phpt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt index 920905830a9..3d527e5ffec 100644 --- a/ext/pdo_dblib/tests/bug_45876.phpt +++ b/ext/pdo_dblib/tests/bug_45876.phpt @@ -14,8 +14,8 @@ $stmt->execute(); var_dump($stmt->getColumnMeta(0)); $stmt = null; ?> ---EXPECT-- -array(8) { +--EXPECTF-- +array(10) { ["max_length"]=> int(255) ["precision"]=> @@ -26,6 +26,10 @@ array(8) { string(13) "TABLE_CATALOG" ["native_type"]=> string(4) "char" + ["native_type_id"]=> + int(%d) + ["native_usertype_id"]=> + int(%d) ["name"]=> string(13) "TABLE_CATALOG" ["len"]=> From 1e1500a2bc30e0f7b0846e16567ffb3728f57eef Mon Sep 17 00:00:00 2001 From: Adam Baratz Date: Wed, 6 Apr 2016 12:18:53 +0200 Subject: [PATCH 03/18] return zvals instead of strings, cast or not based on stringify attribute --- ext/pdo_dblib/dblib_stmt.c | 236 ++++++++++++++++++++--------- ext/pdo_dblib/tests/bug_38955.phpt | 8 +- ext/pdo_dblib/tests/bug_45876.phpt | 4 +- ext/pdo_dblib/tests/bug_47588.phpt | 6 +- ext/pdo_dblib/tests/types.phpt | 66 ++++++++ 5 files changed, 242 insertions(+), 78 deletions(-) create mode 100644 ext/pdo_dblib/tests/types.phpt diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 49b75ee2bb4..6098ae515dd 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -232,7 +232,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno) } col->maxlen = dbcollen(H->link, colno+1); - col->param_type = PDO_PARAM_STR; + col->param_type = PDO_PARAM_ZVAL; return 1; } @@ -245,78 +245,161 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, pdo_dblib_db_handle *H = S->H; int coltype; - unsigned int tmp_len; - char *tmp_ptr = NULL; + char *data, *tmp_data; + unsigned int data_len, tmp_data_len; + zval *zv = NULL; coltype = dbcoltype(H->link, colno+1); + data = dbdata(H->link, colno+1); + data_len = dbdatlen(H->link, colno+1); - *len = dbdatlen(H->link, colno+1); - *ptr = dbdata(H->link, colno+1); + if (data_len != 0 || data != NULL) { + if (stmt->dbh->stringify) { + switch (coltype) { + case SQLFLT4: + case SQLFLT8: + case SQLINT4: + case SQLINT2: + case SQLINT1: + case SQLBIT: { + if (dbwillconvert(coltype, SQLCHAR)) { + tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */ + tmp_data = emalloc(tmp_data_len); + data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1); - if (*len == 0 && *ptr == NULL) { - return 1; + zv = emalloc(sizeof(zval)); + ZVAL_STRING(zv, tmp_data); + + efree(tmp_data); + } + break; + } + } + } + + if (!zv) { + switch (coltype) { + case SQLCHAR: + case SQLVARCHAR: + case SQLTEXT: { +#if ilia_0 + while (data_len>0 && data[data_len-1] == ' ') { /* nuke trailing whitespace */ + data_len--; + } +#endif + } + case SQLVARBINARY: + case SQLBINARY: + case SQLIMAGE: { + zv = emalloc(sizeof(zval)); + ZVAL_STRINGL(zv, data, data_len); + + break; + } + case SQLDATETIME: + case SQLDATETIM4: { + int dl; + DBDATEREC di; + DBDATEREC dt; + + dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1); + dbdatecrack(H->link, &di, (DBDATETIME *) &dt); + + dl = spprintf(&tmp_data, 20, "%d-%02d-%02d %02d:%02d:%02d", +#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB) + di.year, di.month, di.day, di.hour, di.minute, di.second +#else + di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond +#endif + ); + + zv = emalloc(sizeof(zval)); + ZVAL_STRINGL(zv, tmp_data, dl); + + efree(tmp_data); + + break; + } + case SQLFLT4: { + zv = emalloc(sizeof(zval)); + ZVAL_DOUBLE(zv, (double) (*(DBFLT4 *) data)); + + break; + } + case SQLFLT8: { + zv = emalloc(sizeof(zval)); + ZVAL_DOUBLE(zv, (double) (*(DBFLT8 *) data)); + + break; + } + case SQLINT4: { + zv = emalloc(sizeof(zval)); + ZVAL_LONG(zv, (long) ((int) *(DBINT *) data)); + + break; + } + case SQLINT2: { + zv = emalloc(sizeof(zval)); + ZVAL_LONG(zv, (long) ((int) *(DBSMALLINT *) data)); + + break; + } + case SQLINT1: + case SQLBIT: { + zv = emalloc(sizeof(zval)); + ZVAL_LONG(zv, (long) ((int) *(DBTINYINT *) data)); + + break; + } + case SQLMONEY: + case SQLMONEY4: + case SQLMONEYN: { + DBFLT8 money_value; + dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1); + + zv = emalloc(sizeof(zval)); + ZVAL_DOUBLE(zv, money_value); + + if (stmt->dbh->stringify) { + convert_to_string(zv); + } + + break; + } +#ifdef SQLUNIQUE + case SQLUNIQUE: { +#else + case 36: { /* FreeTDS hack */ +#endif + zv = emalloc(sizeof(zval)); + ZVAL_STRINGL(zv, data, 16); /* uniqueidentifier is a 16-byte binary number */ + + break; + } + default: { + if (dbwillconvert(coltype, SQLCHAR)) { + tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */ + tmp_data = emalloc(tmp_data_len); + data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1); + + zv = emalloc(sizeof(zval)); + ZVAL_STRING(zv, tmp_data); + + efree(tmp_data); + } + + break; + } + } + } } - switch (coltype) { - case SQLVARBINARY: - case SQLBINARY: - case SQLIMAGE: - case SQLTEXT: - /* FIXME: Above types should be returned as a stream as they can be VERY large */ - case SQLCHAR: - case SQLVARCHAR: - tmp_ptr = emalloc(*len + 1); - memcpy(tmp_ptr, *ptr, *len); - tmp_ptr[*len] = '\0'; - *ptr = tmp_ptr; - break; - case SQLMONEY: - case SQLMONEY4: - case SQLMONEYN: { - DBFLT8 money_value; - dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8); - *len = spprintf(&tmp_ptr, 0, "%.4f", money_value); - *ptr = tmp_ptr; - break; - } - case SQLUNIQUE: { - *len = 37; - tmp_ptr = emalloc(*len + 1); - *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len); - php_strtoupper(tmp_ptr, *len); - tmp_ptr[36] = '\0'; - *ptr = tmp_ptr; - break; - } - case SQLDATETIM4: - case SQLDATETIME: { - DBDATETIME dt; - DBDATEREC di; - - dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1); - dbdatecrack(H->link, &di, &dt); - - *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d", -#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB) - di.year, di.month, di.day, di.hour, di.minute, di.second -#else - di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond -#endif - ); - - *ptr = (char*) tmp_ptr; - break; - } - default: - if (dbwillconvert(coltype, SQLCHAR)) { - tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */ - tmp_ptr = emalloc(tmp_len); - *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1); - *ptr = tmp_ptr; - } else { - *len = 0; /* FIXME: Silently fails and returns null on conversion errors */ - *ptr = NULL; - } + if (zv != NULL) { + *ptr = (char*)zv; + *len = sizeof(zval); + } else { + *ptr = NULL; + *len = 0; } *caller_frees = 1; @@ -335,6 +418,7 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data; pdo_dblib_db_handle *H = S->H; DBTYPEINFO* dbtypeinfo; + int coltype; if(colno >= stmt->column_count || colno < 0) { return FAILURE; @@ -346,14 +430,28 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva if(!dbtypeinfo) return FAILURE; + coltype = dbcoltype(H->link, colno+1); + add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) ); add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision ); add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale ); add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1)); - add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1))); - add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1)); + add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype)); + add_assoc_long(return_value, "native_type_id", coltype); add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1)); + switch (coltype) { + case SQLBIT: + case SQLINT1: + case SQLINT2: + case SQLINT4: + add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT); + break; + default: + add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR); + break; + } + return 1; } diff --git a/ext/pdo_dblib/tests/bug_38955.phpt b/ext/pdo_dblib/tests/bug_38955.phpt index 1954ed460b5..57adbf6c404 100644 --- a/ext/pdo_dblib/tests/bug_38955.phpt +++ b/ext/pdo_dblib/tests/bug_38955.phpt @@ -37,21 +37,21 @@ array(4) { [0]=> array(1) { ["val"]=> - string(1) "1" + int(1) } [1]=> array(1) { ["val"]=> - string(1) "2" + int(2) } [2]=> array(1) { ["val"]=> - string(1) "3" + int(3) } [3]=> array(1) { ["val"]=> - string(1) "4" + int(4) } } diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt index 3d527e5ffec..5f1026e6232 100644 --- a/ext/pdo_dblib/tests/bug_45876.phpt +++ b/ext/pdo_dblib/tests/bug_45876.phpt @@ -30,10 +30,10 @@ array(10) { int(%d) ["native_usertype_id"]=> int(%d) + ["pdo_type"]=> + int(2) ["name"]=> string(13) "TABLE_CATALOG" ["len"]=> int(255) - ["pdo_type"]=> - int(2) } diff --git a/ext/pdo_dblib/tests/bug_47588.phpt b/ext/pdo_dblib/tests/bug_47588.phpt index d8f424e8728..262720f632b 100644 --- a/ext/pdo_dblib/tests/bug_47588.phpt +++ b/ext/pdo_dblib/tests/bug_47588.phpt @@ -23,21 +23,21 @@ array(3) { [0]=> array(2) { ["My Field"]=> - string(1) "1" + int(1) ["Another Field"]=> string(11) "test_string" } [1]=> array(2) { ["My Field"]=> - string(1) "2" + int(2) ["Another Field"]=> string(11) "test_string" } [2]=> array(2) { ["My Field"]=> - string(1) "3" + int(3) ["Another Field"]=> string(11) "test_string" } diff --git a/ext/pdo_dblib/tests/types.phpt b/ext/pdo_dblib/tests/types.phpt new file mode 100644 index 00000000000..dd849adcf81 --- /dev/null +++ b/ext/pdo_dblib/tests/types.phpt @@ -0,0 +1,66 @@ +--TEST-- +PDO_DBLIB: Column data types, with or without stringifying +--SKIPIF-- + +--FILE-- +query($sql); +$row = $stmt->fetch(PDO::FETCH_ASSOC); + +var_dump($row['char'] === 'foo'); +var_dump($row['datetime'] === '2030-01-01 23:59:59'); +var_dump($row['false'] === 0); +var_dump($row['float'] === 10.5); +var_dump($row['int'] === 1000); +var_dump($row['money'] === 10.5); +var_dump($row['smalldatetime'] === '1950-01-18 23:00:00'); +var_dump($row['true'] === 1); + +$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); +$stmt = $db->query($sql); +$row = $stmt->fetch(PDO::FETCH_ASSOC); + +var_dump($row['char'] === 'foo'); +var_dump($row['datetime'] === '2030-01-01 23:59:59'); +var_dump($row['false'] === '0'); +var_dump($row['float'] === '10.5'); +var_dump($row['int'] === '1000'); +var_dump($row['money'] === '10.5'); +var_dump($row['smalldatetime'] === '1950-01-18 23:00:00'); +var_dump($row['true'] === '1'); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) From d54eafb349975652033bd6705ca1b61eae9aa5ec Mon Sep 17 00:00:00 2001 From: Fatih ACAR Date: Fri, 4 Mar 2016 11:17:45 +0100 Subject: [PATCH 04/18] make opcache lockfile path configurable Signed-off-by: William Dauchy Signed-off-by: Baptiste Daroussin Signed-off-by: Fatih Acar --- ext/opcache/README | 3 +++ ext/opcache/ZendAccelerator.h | 1 + ext/opcache/zend_accelerator_module.c | 2 ++ ext/opcache/zend_shared_alloc.c | 11 +++++++---- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ext/opcache/README b/ext/opcache/README index c0744401307..11c9c2748bf 100644 --- a/ext/opcache/README +++ b/ext/opcache/README @@ -213,3 +213,6 @@ opcache.mmap_base processes have to map shared memory into the same address space. This directive allows to manually fix the "Unable to reattach to base address" errors. + +opcache.lockfile_path (default "/tmp") + Absolute path used to store shared lockfiles. diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index 99db6a25645..42a34aa72b1 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -217,6 +217,7 @@ typedef struct _zend_accel_directives { zend_long max_file_size; zend_long interned_strings_buffer; char *restrict_api; + char *lockfile_path; #ifdef HAVE_OPCACHE_FILE_CACHE char *file_cache; zend_bool file_cache_only; diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 2fabc8cb3c7..e8c274e5160 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -298,6 +298,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.lockfile_path" , "/tmp" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.lockfile_path, zend_accel_globals, accel_globals) #ifdef ZEND_WIN32 STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals) @@ -710,6 +711,7 @@ static ZEND_FUNCTION(opcache_get_configuration) add_assoc_bool(&directives, "opcache.fast_shutdown", ZCG(accel_directives).fast_shutdown); add_assoc_bool(&directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(&directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level); + add_assoc_string(&directives, "opcache.lockfile_path", STRING_NOT_NULL(ZCG(accel_directives).lockfile_path)); #ifdef HAVE_OPCACHE_FILE_CACHE add_assoc_string(&directives, "opcache.file_cache", ZCG(accel_directives).file_cache ? ZCG(accel_directives).file_cache : ""); diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 663d905c8d7..ff42c4cf0b8 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -38,7 +38,6 @@ # include "sys/mman.h" #endif -#define TMP_DIR "/tmp" #define SEM_FILENAME_PREFIX ".ZendSem." #define S_H(s) g_shared_alloc_handler->s @@ -55,7 +54,7 @@ zend_smm_shared_globals *smm_shared_globals; static MUTEX_T zts_lock; #endif int lock_file; -static char lockfile_name[sizeof(TMP_DIR) + sizeof(SEM_FILENAME_PREFIX) + 8]; +static char lockfile_name[MAXPATHLEN]; #endif static const zend_shared_memory_handler_entry handler_table[] = { @@ -75,7 +74,7 @@ static const zend_shared_memory_handler_entry handler_table[] = { }; #ifndef ZEND_WIN32 -void zend_shared_alloc_create_lock(void) +void zend_shared_alloc_create_lock(char *lockfile_path) { int val; @@ -83,7 +82,7 @@ void zend_shared_alloc_create_lock(void) zts_lock = tsrm_mutex_alloc(); #endif - sprintf(lockfile_name, "%s/%sXXXXXX", TMP_DIR, SEM_FILENAME_PREFIX); + snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX); lock_file = mkstemp(lockfile_name); fchmod(lock_file, 0666); @@ -163,7 +162,11 @@ int zend_shared_alloc_startup(size_t requested_size) smm_shared_globals = &tmp_shared_globals; ZSMMG(shared_free) = requested_size; /* goes to tmp_shared_globals.shared_free */ +#ifndef ZEND_WIN32 + zend_shared_alloc_create_lock(ZCG(accel_directives).lockfile_path); +#else zend_shared_alloc_create_lock(); +#endif if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) { char *model = ZCG(accel_directives).memory_model; From 02fc9cb31fe17408a0d13c9a05fb84acc5deadc4 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 13:55:32 +0200 Subject: [PATCH 05/18] skip test on 32-bit The Postgres INT8 datatype is handled as string on 32-bit --- ext/pdo_pgsql/tests/bug62498.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/pdo_pgsql/tests/bug62498.phpt b/ext/pdo_pgsql/tests/bug62498.phpt index e4ca3dec4f6..ed25899990c 100644 --- a/ext/pdo_pgsql/tests/bug62498.phpt +++ b/ext/pdo_pgsql/tests/bug62498.phpt @@ -1,11 +1,12 @@ --TEST-- -PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used) +PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used), 64-bit --SKIPIF-- --FILE-- Date: Wed, 6 Apr 2016 14:05:25 +0200 Subject: [PATCH 06/18] add 32-bit specific variont for #62498 --- ext/pdo_pgsql/tests/bug62498-32bit.phpt | 185 ++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 ext/pdo_pgsql/tests/bug62498-32bit.phpt diff --git a/ext/pdo_pgsql/tests/bug62498-32bit.phpt b/ext/pdo_pgsql/tests/bug62498-32bit.phpt new file mode 100644 index 00000000000..3727ed7d118 --- /dev/null +++ b/ext/pdo_pgsql/tests/bug62498-32bit.phpt @@ -0,0 +1,185 @@ +--TEST-- +PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used), 32-bit +--SKIPIF-- + 4) die("skip relevant for 32-bit only"); +?> +--FILE-- +setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + +// create the table +$db->exec("CREATE TEMPORARY TABLE bugtest_62498 (int2col INT2, int4col INT4, int8col INT8, stringcol VARCHAR(255), boolcol BOOLEAN, datecol DATE, textcol TEXT, tscol TIMESTAMP, byteacol BYTEA)"); + +// insert some data +$statement = $db->prepare("INSERT INTO bugtest_62498 (int2col, int4col, int8col, stringcol, boolcol, datecol, textcol, tscol, byteacol) VALUES (:int2val, :int4val, :int8val, :stringval, :boolval, :dateval, :textval, :tsval, :byteaval)"); +$vals = array( + "int2val" => "42", + "int4val" => "42", + "int8val" => "42", + "stringval" => "The Answer", + "boolval" => true, + "dateval" => '2015-12-14', + "textval" => "some text", + "tsval" => 19990108, + "byteaval" => 0, +); +$statement->execute($vals); + +$select = $db->query('SELECT int2col, int4col, int8col, stringcol, boolcol, datecol, textcol, tscol, byteacol FROM bugtest_62498'); +$meta = []; +for ($i=0; $i < count($vals); $i++) { + $meta[] = $select->getColumnMeta($i); +} +var_dump($meta); + +?> +Done +--EXPECT-- +Begin test... +array(9) { + [0]=> + array(6) { + ["pgsql:oid"]=> + int(21) + ["native_type"]=> + string(4) "int2" + ["name"]=> + string(7) "int2col" + ["len"]=> + int(2) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(1) + } + [1]=> + array(6) { + ["pgsql:oid"]=> + int(23) + ["native_type"]=> + string(4) "int4" + ["name"]=> + string(7) "int4col" + ["len"]=> + int(4) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(1) + } + [2]=> + array(6) { + ["pgsql:oid"]=> + int(20) + ["native_type"]=> + string(4) "int8" + ["name"]=> + string(7) "int8col" + ["len"]=> + int(8) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(2) + } + [3]=> + array(6) { + ["pgsql:oid"]=> + int(1043) + ["native_type"]=> + string(7) "varchar" + ["name"]=> + string(9) "stringcol" + ["len"]=> + int(-1) + ["precision"]=> + int(259) + ["pdo_type"]=> + int(2) + } + [4]=> + array(6) { + ["pgsql:oid"]=> + int(16) + ["native_type"]=> + string(4) "bool" + ["name"]=> + string(7) "boolcol" + ["len"]=> + int(1) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(5) + } + [5]=> + array(6) { + ["pgsql:oid"]=> + int(1082) + ["native_type"]=> + string(4) "date" + ["name"]=> + string(7) "datecol" + ["len"]=> + int(4) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(2) + } + [6]=> + array(6) { + ["pgsql:oid"]=> + int(25) + ["native_type"]=> + string(4) "text" + ["name"]=> + string(7) "textcol" + ["len"]=> + int(-1) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(2) + } + [7]=> + array(6) { + ["pgsql:oid"]=> + int(1114) + ["native_type"]=> + string(9) "timestamp" + ["name"]=> + string(5) "tscol" + ["len"]=> + int(8) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(2) + } + [8]=> + array(6) { + ["pgsql:oid"]=> + int(17) + ["native_type"]=> + string(5) "bytea" + ["name"]=> + string(8) "byteacol" + ["len"]=> + int(-1) + ["precision"]=> + int(-1) + ["pdo_type"]=> + int(3) + } +} +Done From c256a8c25e3c24a66271ba1d749591f2fcf84628 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 14:13:43 +0200 Subject: [PATCH 07/18] update NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index e3d2d264264..24da274e037 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,7 @@ PHP NEWS - Opcache: . Fixed bug #71843 (null ptr deref ZEND_RETURN_SPEC_CONST_HANDLER). (Laruence) + . Made opcache lockfile path configurable. (Fatih ACAR) - PDO: . Fixed bug #52098 (Own PDOStatement implementation ignore __call()). From ed3edc2f05c7be9c498aee64de2ad5a796456135 Mon Sep 17 00:00:00 2001 From: Adam Baratz Date: Fri, 26 Feb 2016 12:01:59 -0500 Subject: [PATCH 08/18] fix bug #71667 (emulate how mssql extension names "computed" columns) --- ext/pdo_dblib/dblib_driver.c | 1 + ext/pdo_dblib/dblib_stmt.c | 20 +++++++++++++----- ext/pdo_dblib/php_pdo_dblib_int.h | 1 + ext/pdo_dblib/tests/bug_71667.phpt | 34 ++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 ext/pdo_dblib/tests/bug_71667.phpt diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index 9d9424a8b20..ad54ae57b3e 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -101,6 +101,7 @@ static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len stmt->driver_data = S; stmt->methods = &dblib_stmt_methods; stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; + S->computed_column_name_count = 0; S->err.sqlstate = stmt->error_code; return 1; diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 6098ae515dd..a1055434d37 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -218,17 +218,27 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno) return FAILURE; } + if (colno == 0) { + S->computed_column_name_count = 0; + } + col = &stmt->columns[colno]; fname = (char*)dbcolname(H->link, colno+1); if (fname && *fname) { col->name = zend_string_init(fname, strlen(fname), 0); } else { - char buf[16]; - int len; - - len = snprintf(buf, sizeof(buf), "computed%d", colno); - col->name = zend_string_init(buf, len, 0); + if (S->computed_column_name_count > 0) { + char buf[16]; + int len; + + len = snprintf(buf, sizeof(buf), "computed%d", S->computed_column_name_count); + col->name = zend_string_init(buf, len, 0); + } else { + col->name = zend_string_init("computed", strlen("computed"), 0); + } + + S->computed_column_name_count++; } col->maxlen = dbcollen(H->link, colno+1); diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h index 5b47922abef..01586881d55 100644 --- a/ext/pdo_dblib/php_pdo_dblib_int.h +++ b/ext/pdo_dblib/php_pdo_dblib_int.h @@ -118,6 +118,7 @@ typedef struct { typedef struct { pdo_dblib_db_handle *H; pdo_dblib_err err; + unsigned int computed_column_name_count; } pdo_dblib_stmt; typedef struct { diff --git a/ext/pdo_dblib/tests/bug_71667.phpt b/ext/pdo_dblib/tests/bug_71667.phpt new file mode 100644 index 00000000000..1c5005fd6a2 --- /dev/null +++ b/ext/pdo_dblib/tests/bug_71667.phpt @@ -0,0 +1,34 @@ +--TEST-- +PDO_DBLIB: Emulate how mssql extension names "computed" columns +--SKIPIF-- + +--FILE-- +prepare("SELECT 1, 2 AS named, 3"); +$stmt->execute(); +var_dump($stmt->fetchAll()); + +?> +--EXPECT-- +array(1) { + [0]=> + array(6) { + ["computed"]=> + string(1) "1" + [0]=> + string(1) "1" + ["named"]=> + string(1) "2" + [1]=> + string(1) "2" + ["computed1"]=> + string(1) "3" + [2]=> + string(1) "3" + } +} From ea64d290fe2801b033741de1cff28647928d6958 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 14:44:23 +0200 Subject: [PATCH 09/18] fix test --- ext/pdo_dblib/tests/bug_68957.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_dblib/tests/bug_68957.phpt b/ext/pdo_dblib/tests/bug_68957.phpt index 3d6e2fd13da..47ff461bb3e 100644 --- a/ext/pdo_dblib/tests/bug_68957.phpt +++ b/ext/pdo_dblib/tests/bug_68957.phpt @@ -21,7 +21,7 @@ Array ( [0] => Array ( - [computed0] => 1 + [computed] => 1 [0] => 1 ) From e9d65160e85fb08d9bd08202b60a8b19b446c646 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 6 Apr 2016 17:17:10 +0300 Subject: [PATCH 10/18] Fixed bug #71978 (Existence of return type hint affects other compatibility rules) --- NEWS | 2 ++ Zend/tests/return_types/bug71978.phpt | 21 +++++++++++++++ Zend/zend_inheritance.c | 38 ++++++++++++++++++--------- 3 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 Zend/tests/return_types/bug71978.phpt diff --git a/NEWS b/NEWS index 24da274e037..56e81c9d92e 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? 2016 PHP 7.0.6 - Core: + . Fixed bug #71978 (Existence of return type hint affects other compatibility + rules). (Dmitry) . Fixed bug #71930 (_zval_dtor_func: Assertion `(arr)->gc.refcount <= 1' failed). (Laruence) . Fixed bug #71922 (Crash on assert(new class{})). (Nikita) diff --git a/Zend/tests/return_types/bug71978.phpt b/Zend/tests/return_types/bug71978.phpt new file mode 100644 index 00000000000..e3c84402123 --- /dev/null +++ b/Zend/tests/return_types/bug71978.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #71978 (Existence of return type hint affects other compatibility rules) +--FILE-- + +--EXPECTF-- +Warning: Declaration of B::foo(string $a) should be compatible with A::foo(int $a) in %s on line %d + +Warning: Declaration of B1::foo(string $a): int should be compatible with A1::foo(int $a): int in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 55a9fdc9095..e6721879ee8 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -243,11 +243,6 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf return 0; } - if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) { - /* incompatible nullability */ - return 0; - } - return 1; } /* }}} */ @@ -324,6 +319,11 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c return 0; } + if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) { + /* incompatible nullability */ + return 0; + } + /* by-ref constraints on arguments are invariant */ if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) { return 0; @@ -570,17 +570,31 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * } if (child->common.prototype && ( - child->common.prototype->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_HAS_RETURN_TYPE) + child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT )) { - if (UNEXPECTED(!zend_do_perform_implementation_check(child, child->common.prototype))) { - zend_string *method_prototype = zend_get_function_declaration(child->common.prototype); - zend_string *child_prototype = zend_get_function_declaration(child); - zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype)); + parent = child->common.prototype; + } + if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) { + int error_level; + const char *error_verb; + + if (child->common.prototype && ( + child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT + )) { + error_level = E_COMPILE_ERROR; + error_verb = "must"; + } else if ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && + (!(child->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + !zend_do_perform_type_hint_check(child, child->common.arg_info - 1, parent, parent->common.arg_info - 1))) { + error_level = E_COMPILE_ERROR; + error_verb = "must"; + } else { + error_level = E_WARNING; + error_verb = "should"; } - } else if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) { zend_string *method_prototype = zend_get_function_declaration(parent); zend_string *child_prototype = zend_get_function_declaration(child); - zend_error(E_WARNING, "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype)); + zend_error(error_level, "Declaration of %s %s be compatible with %s", ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(method_prototype)); zend_string_free(child_prototype); zend_string_free(method_prototype); } From 052c1d337ce52b1b2c3be83232a2b2da6a4662bd Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 16:19:48 +0200 Subject: [PATCH 11/18] fix indent --- ext/pdo_pgsql/pgsql_statement.c | 80 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 6a18d6dfb0b..43b25f9430a 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -605,46 +605,46 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r array_init(return_value); add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type); - switch (S->cols[colno].pgsql_type) { - case BOOLOID: - add_assoc_string(return_value, "native_type", BOOLLABEL); - break; - case BYTEAOID: - add_assoc_string(return_value, "native_type", BYTEALABEL); - break; - case INT8OID: - add_assoc_string(return_value, "native_type", INT8LABEL); - break; - case INT2OID: - add_assoc_string(return_value, "native_type", INT2LABEL); - break; - case INT4OID: - add_assoc_string(return_value, "native_type", INT4LABEL); - break; - case TEXTOID: - add_assoc_string(return_value, "native_type", TEXTLABEL); - break; - case VARCHAROID: - add_assoc_string(return_value, "native_type", VARCHARLABEL); - break; - case DATEOID: - add_assoc_string(return_value, "native_type", DATELABEL); - break; - case TIMESTAMPOID: - add_assoc_string(return_value, "native_type", TIMESTAMPLABEL); - break; - default: - /* Fetch metadata from Postgres system catalogue */ - spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type); - res = PQexec(S->H->server, q); - efree(q); - status = PQresultStatus(res); - if (status == PGRES_TUPLES_OK && 1 == PQntuples(res)) { - add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0)); - } - PQclear(res); - } - return 1; + switch (S->cols[colno].pgsql_type) { + case BOOLOID: + add_assoc_string(return_value, "native_type", BOOLLABEL); + break; + case BYTEAOID: + add_assoc_string(return_value, "native_type", BYTEALABEL); + break; + case INT8OID: + add_assoc_string(return_value, "native_type", INT8LABEL); + break; + case INT2OID: + add_assoc_string(return_value, "native_type", INT2LABEL); + break; + case INT4OID: + add_assoc_string(return_value, "native_type", INT4LABEL); + break; + case TEXTOID: + add_assoc_string(return_value, "native_type", TEXTLABEL); + break; + case VARCHAROID: + add_assoc_string(return_value, "native_type", VARCHARLABEL); + break; + case DATEOID: + add_assoc_string(return_value, "native_type", DATELABEL); + break; + case TIMESTAMPOID: + add_assoc_string(return_value, "native_type", TIMESTAMPLABEL); + break; + default: + /* Fetch metadata from Postgres system catalogue */ + spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type); + res = PQexec(S->H->server, q); + efree(q); + status = PQresultStatus(res); + if (status == PGRES_TUPLES_OK && 1 == PQntuples(res)) { + add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0)); + } + PQclear(res); + } + return 1; } static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt) From aeb9c81c09a70c19c53a6f758ac992b67a48ce2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20S=C3=BDkora?= Date: Tue, 2 Jul 2013 12:38:38 +0200 Subject: [PATCH 12/18] PostgreSQL's PDOStatement::getColumnMeta() fills in table's name. --- ext/pdo_pgsql/pgsql_statement.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 43b25f9430a..fca8598ac99 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -587,12 +587,40 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulon return 1; } +static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGconn *conn) +{ + char *table_name = NULL; + PGresult *tmp_res; + char *querystr = NULL; + + spprintf(&querystr, 0, "SELECT RELNAME FROM PG_CLASS WHERE OID=%d", oid); + + if ((tmp_res = PQexec(conn, querystr)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) { + if (tmp_res) { + PQclear(tmp_res); + } + efree(querystr); + return 0; + } + efree(querystr); + + if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) { + PQclear(tmp_res); + return 0; + } + + PQclear(tmp_res); + return table_name; +} + static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; PGresult *res; char *q=NULL; ExecStatusType status; + Oid table_oid; + char *table_name=NULL; if (!S->result) { return FAILURE; @@ -605,6 +633,13 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r array_init(return_value); add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type); + table_oid = PQftable(S->result, colno); + add_assoc_long(return_value, "pgsql:table_oid", table_oid); + table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server); + if (table_name) { + add_assoc_string(return_value, "table", table_name, 1); + } + switch (S->cols[colno].pgsql_type) { case BOOLOID: add_assoc_string(return_value, "native_type", BOOLLABEL); From 26f9aa721178a35ce6a0e46f548c4ddb2537769c Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 17:42:23 +0200 Subject: [PATCH 13/18] fix tests --- ext/pdo_pgsql/tests/bug62498-32bit.phpt | 56 ++++++++++++++++++++----- ext/pdo_pgsql/tests/bug62498.phpt | 56 ++++++++++++++++++++----- 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/ext/pdo_pgsql/tests/bug62498-32bit.phpt b/ext/pdo_pgsql/tests/bug62498-32bit.phpt index 3727ed7d118..edcf52048c8 100644 --- a/ext/pdo_pgsql/tests/bug62498-32bit.phpt +++ b/ext/pdo_pgsql/tests/bug62498-32bit.phpt @@ -43,13 +43,17 @@ var_dump($meta); ?> Done ---EXPECT-- +--EXPECTF-- Begin test... array(9) { [0]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(21) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int2" ["name"]=> @@ -62,9 +66,13 @@ array(9) { int(1) } [1]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(23) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int4" ["name"]=> @@ -77,9 +85,13 @@ array(9) { int(1) } [2]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(20) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int8" ["name"]=> @@ -92,9 +104,13 @@ array(9) { int(2) } [3]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1043) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(7) "varchar" ["name"]=> @@ -107,9 +123,13 @@ array(9) { int(2) } [4]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(16) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "bool" ["name"]=> @@ -122,9 +142,13 @@ array(9) { int(5) } [5]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1082) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "date" ["name"]=> @@ -137,9 +161,13 @@ array(9) { int(2) } [6]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(25) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "text" ["name"]=> @@ -152,9 +180,13 @@ array(9) { int(2) } [7]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1114) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(9) "timestamp" ["name"]=> @@ -167,9 +199,13 @@ array(9) { int(2) } [8]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(17) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(5) "bytea" ["name"]=> diff --git a/ext/pdo_pgsql/tests/bug62498.phpt b/ext/pdo_pgsql/tests/bug62498.phpt index ed25899990c..53d42fc3fa8 100644 --- a/ext/pdo_pgsql/tests/bug62498.phpt +++ b/ext/pdo_pgsql/tests/bug62498.phpt @@ -43,13 +43,17 @@ var_dump($meta); ?> Done ---EXPECT-- +--EXPECTF-- Begin test... array(9) { [0]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(21) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int2" ["name"]=> @@ -62,9 +66,13 @@ array(9) { int(1) } [1]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(23) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int4" ["name"]=> @@ -77,9 +85,13 @@ array(9) { int(1) } [2]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(20) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "int8" ["name"]=> @@ -92,9 +104,13 @@ array(9) { int(1) } [3]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1043) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(7) "varchar" ["name"]=> @@ -107,9 +123,13 @@ array(9) { int(2) } [4]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(16) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "bool" ["name"]=> @@ -122,9 +142,13 @@ array(9) { int(5) } [5]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1082) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "date" ["name"]=> @@ -137,9 +161,13 @@ array(9) { int(2) } [6]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(25) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(4) "text" ["name"]=> @@ -152,9 +180,13 @@ array(9) { int(2) } [7]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(1114) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(9) "timestamp" ["name"]=> @@ -167,9 +199,13 @@ array(9) { int(2) } [8]=> - array(6) { + array(8) { ["pgsql:oid"]=> int(17) + ["pgsql:table_oid"]=> + int(%d) + ["table"]=> + string(13) "bugtest_62498" ["native_type"]=> string(5) "bytea" ["name"]=> From 6489edb9585112835f1dcbbd68140b2e9e3de1c5 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 6 Apr 2016 18:05:39 +0200 Subject: [PATCH 14/18] fix merge mistake --- ext/pdo_pgsql/pgsql_statement.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index fca8598ac99..a6a69ac3d04 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -637,7 +637,7 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r add_assoc_long(return_value, "pgsql:table_oid", table_oid); table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server); if (table_name) { - add_assoc_string(return_value, "table", table_name, 1); + add_assoc_string(return_value, "table", table_name); } switch (S->cols[colno].pgsql_type) { From 088f55ae74d8cd316fd33f1828f28472409cfb21 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 7 Apr 2016 00:59:21 +0300 Subject: [PATCH 15/18] Fixed build --- Zend/zend_inheritance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index e6721879ee8..9042b2f0a2d 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -577,6 +577,8 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) { int error_level; const char *error_verb; + zend_string *method_prototype = zend_get_function_declaration(parent); + zend_string *child_prototype = zend_get_function_declaration(child); if (child->common.prototype && ( child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT @@ -592,8 +594,6 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * error_level = E_WARNING; error_verb = "should"; } - zend_string *method_prototype = zend_get_function_declaration(parent); - zend_string *child_prototype = zend_get_function_declaration(child); zend_error(error_level, "Declaration of %s %s be compatible with %s", ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(method_prototype)); zend_string_free(child_prototype); zend_string_free(method_prototype); From b31240f995a742b363074e0079b1aef4e577a27e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 7 Apr 2016 01:01:11 +0300 Subject: [PATCH 16/18] Optimized array_fill(). This is a perfect function for fast creation of packed arrays. --- ext/standard/array.c | 80 ++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 289870ac1f2..a0cdd91d855 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2000,34 +2000,72 @@ PHP_FUNCTION(array_fill) zval *val; zend_long start_key, num; +#ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "llz", &start_key, &num, &val) == FAILURE) { return; } +#else + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_LONG(start_key) + Z_PARAM_LONG(num) + Z_PARAM_ZVAL(val) + ZEND_PARSE_PARAMETERS_END(); +#endif - if (num < 0) { - php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); - RETURN_FALSE; - } - - /* allocate an array for return */ - array_init_size(return_value, (uint32_t)num); - - if (num == 0) { - return; - } - - num--; - zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, val); - Z_TRY_ADDREF_P(val); - - while (num--) { - if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), val) != NULL) { - Z_TRY_ADDREF_P(val); - } else { - zval_dtor(return_value); + if (EXPECTED(num > 0)) { + if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) { + php_error_docref(NULL, E_WARNING, "Too many elements"); + RETURN_FALSE; + } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) { php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied"); RETURN_FALSE; + } else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) { + /* create packed array */ + Bucket *p; + zend_long n; + + array_init_size(return_value, (uint32_t)(start_key + num)); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + Z_ARRVAL_P(return_value)->nNumUsed = start_key + num; + Z_ARRVAL_P(return_value)->nNumOfElements = num; + Z_ARRVAL_P(return_value)->nInternalPointer = start_key; + + if (Z_REFCOUNTED_P(val)) { + GC_REFCOUNT(Z_COUNTED_P(val)) += num; + } + + p = Z_ARRVAL_P(return_value)->arData; + n = start_key; + + while (start_key--) { + ZVAL_UNDEF(&p->val); + p++; + } + while (num--) { + ZVAL_COPY_VALUE(&p->val, val); + p->h = n++; + p->key = NULL; + p++; + } + } else { + /* create hash */ + array_init_size(return_value, (uint32_t)num); + zend_hash_real_init(Z_ARRVAL_P(return_value), 0); + if (Z_REFCOUNTED_P(val)) { + GC_REFCOUNT(Z_COUNTED_P(val)) += num; + } + zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val); + while (--num) { + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), val); + start_key++; + } } + } else if (EXPECTED(num == 0)) { + array_init(return_value); + return; + } else { + php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); + RETURN_FALSE; } } /* }}} */ From 6467a4eb367fd1174fbed79f014772321f68e8bc Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Thu, 7 Apr 2016 10:25:35 +0900 Subject: [PATCH 17/18] Fixed Bug #71974 Trans sid will always be send, even if cookies are available --- NEWS | 4 ++++ ext/session/session.c | 23 +++++++++++++++-------- ext/session/tests/bug71974.phpt | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 ext/session/tests/bug71974.phpt diff --git a/NEWS b/NEWS index 56e81c9d92e..959f3eb6252 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,10 @@ PHP NEWS . Fixed bug #71820 (pg_fetch_object binds parameters before call constructor). (Anatol) +- Session: + . Fixed bug #71974 (Trans sid will always be send, even if cookies are + available). (Yasuo) + - SPL: . Fixed bug #71838 (Deserializing serialized SPLObjectStorage-Object can't access properties in PHP). (Nikita) diff --git a/ext/session/session.c b/ext/session/session.c index 238ae877f81..e745b96867b 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1483,7 +1483,7 @@ static void ppid2sid(zval *ppid) { PHPAPI void php_session_reset_id(void) /* {{{ */ { int module_number = PS(module_number); - zval *sid; + zval *sid, *data, *ppid; if (!PS(id)) { php_error_docref(NULL, E_WARNING, "Cannot set session ID - session ID is not initialized"); @@ -1523,13 +1523,20 @@ PHPAPI void php_session_reset_id(void) /* {{{ */ } } - if (APPLY_TRANS_SID) { - /* FIXME: Resetting vars are required when - session is stop/start/regenerated. However, - php_url_scanner_reset_vars() resets all vars - including other URL rewrites set by elsewhere. */ - /* php_url_scanner_reset_vars(); */ - php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1); + /* Apply trans sid if sid cookie is not set */ + if (APPLY_TRANS_SID + && (data = zend_hash_str_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE") - 1))) { + ZVAL_DEREF(data); + if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), strlen(PS(session_name))))) { + ZVAL_DEREF(ppid); + } else { + /* FIXME: Resetting vars are required when + session is stop/start/regenerated. However, + php_url_scanner_reset_vars() resets all vars + including other URL rewrites set by elsewhere. */ + /* php_url_scanner_reset_vars(); */ + php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1); + } } } /* }}} */ diff --git a/ext/session/tests/bug71974.phpt b/ext/session/tests/bug71974.phpt new file mode 100644 index 00000000000..b692bce2c5a --- /dev/null +++ b/ext/session/tests/bug71974.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #71974 Trans sid will always be send, even if cookies are available +--SKIPIF-- + +--INI-- +session.save_handler=files +session.auto_start=0 +session.use_cookies=1 +session.use_only_cookies=0 +session.use_trans_sid=1 +session.use_strict_mode=0 +--COOKIE-- +PHPSESSID=1234567890123456789012345678901234567890 +--FILE-- + +abc +--EXPECTF-- +abc + + From 5ab950cb2ca362af3f718179f1da430922c1e0dd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 7 Apr 2016 05:51:49 +0200 Subject: [PATCH 18/18] Remove __halt_compiler from semi-reserved tokens token_get_all() is not capable of dealing with this one correctly. --- Zend/tests/grammar/semi_reserved_001.phpt | 3 --- Zend/tests/grammar/semi_reserved_002.phpt | 3 --- Zend/tests/grammar/semi_reserved_005.phpt | 3 --- Zend/zend_language_parser.y | 2 +- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Zend/tests/grammar/semi_reserved_001.phpt b/Zend/tests/grammar/semi_reserved_001.phpt index 26b3638a47b..48937de39e4 100644 --- a/Zend/tests/grammar/semi_reserved_001.phpt +++ b/Zend/tests/grammar/semi_reserved_001.phpt @@ -80,7 +80,6 @@ class Obj function __FILE__(){ echo __METHOD__, PHP_EOL; } function __DIR__(){ echo __METHOD__, PHP_EOL; } function __NAMESPACE__(){ echo __METHOD__, PHP_EOL; } - function __halt_compiler(){ echo __METHOD__, PHP_EOL; } } $obj = new Obj; @@ -160,7 +159,6 @@ $obj->__LINE__(); $obj->__FILE__(); $obj->__DIR__(); $obj->__NAMESPACE__(); -$obj->__halt_compiler(); echo "\nDone\n"; @@ -240,6 +238,5 @@ Obj::__LINE__ Obj::__FILE__ Obj::__DIR__ Obj::__NAMESPACE__ -Obj::__halt_compiler Done diff --git a/Zend/tests/grammar/semi_reserved_002.phpt b/Zend/tests/grammar/semi_reserved_002.phpt index 483ac8ce809..a082f9ddbb9 100644 --- a/Zend/tests/grammar/semi_reserved_002.phpt +++ b/Zend/tests/grammar/semi_reserved_002.phpt @@ -80,7 +80,6 @@ class Obj static function __FILE__(){ echo __METHOD__, PHP_EOL; } static function __DIR__(){ echo __METHOD__, PHP_EOL; } static function __NAMESPACE__(){ echo __METHOD__, PHP_EOL; } - static function __halt_compiler(){ echo __METHOD__, PHP_EOL; } } Obj::empty(); @@ -158,7 +157,6 @@ Obj::__LINE__(); Obj::__FILE__(); Obj::__DIR__(); Obj::__NAMESPACE__(); -Obj::__halt_compiler(); echo "\nDone\n"; @@ -238,6 +236,5 @@ Obj::__LINE__ Obj::__FILE__ Obj::__DIR__ Obj::__NAMESPACE__ -Obj::__halt_compiler Done diff --git a/Zend/tests/grammar/semi_reserved_005.phpt b/Zend/tests/grammar/semi_reserved_005.phpt index b2b8471bf0d..45d20ad0d83 100644 --- a/Zend/tests/grammar/semi_reserved_005.phpt +++ b/Zend/tests/grammar/semi_reserved_005.phpt @@ -79,7 +79,6 @@ class Obj const __FILE__ = '__FILE__'; const __DIR__ = '__DIR__'; const __NAMESPACE__ = '__NAMESPACE__'; - const __HALT_COMPILER = '__halt_compiler'; } echo Obj::EMPTY, PHP_EOL; @@ -156,7 +155,6 @@ echo Obj::__LINE__, PHP_EOL; echo Obj::__FILE__, PHP_EOL; echo Obj::__DIR__, PHP_EOL; echo Obj::__NAMESPACE__, PHP_EOL; -echo Obj::__HALT_COMPILER, PHP_EOL; echo "\nDone\n"; @@ -235,6 +233,5 @@ __LINE__ __FILE__ __DIR__ __NAMESPACE__ -__halt_compiler Done diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 804ed37473b..9f99453cd44 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -272,7 +272,7 @@ reserved_non_modifiers: | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS - | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER + | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C ; semi_reserved: