Merge branch 'PHP-5.5-security' into PHP-5.5.24

* PHP-5.5-security: (22 commits)
  Fixed bug #69316 (Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER)
  Fix bug #68486 and bug #69218 (segfault in apache2handler with apache 2.4)
  Fix bug #68819 (Fileinfo on specific file causes spurious OOM and/or segfault)
  updated NEWS
  added test for bug #69354
  revert skipif, this should run everywhere
  further ODBC 3.0 compliance
  more compliance with the ODBC 3.0
  test fixes
  Prevent GC from changing zval or object 'color' before they are actually inserted into possible roots buffer.
  sigh, can't even copypaste without screwing up
  oop, put both the error number and message for both db object to the error message
  test fixes
  Fixed bug #69281 (opcache_is_script_cached no longer works)
  Fix typo: unitialized -> uninitialized
  Fix typo: unitialized -> uninitialized
  Fixed bug #68739 (Missing break / control flow). Fixed bug #68740 (NULL Pointer Dereference). Fixed bug #68677 (Use After Free).
  Fixed bug #68739 (Missing break / control flow in curl)
  Fixed bug #68740 (NULL Pointer Dereference)
  Fixed bug #68677 (Use After Free in OPcache)
  ...

Conflicts:
	configure.in
	ext/curl/tests/bug69316.phpt
	main/php_version.h
This commit is contained in:
Stanislav Malyshev 2015-04-12 20:12:38 -07:00
commit 9bbd995679
20 changed files with 109 additions and 33 deletions

View file

@ -1,5 +1,5 @@
--TEST-- --TEST--
Bug #43201 (Crash on using unitialized vals and __get/__set) Bug #43201 (Crash on using uninitialized vals and __get/__set)
--FILE-- --FILE--
<?php <?php
class Foo { class Foo {

View file

@ -147,8 +147,6 @@ ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC)
GC_BENCH_INC(zval_possible_root); GC_BENCH_INC(zval_possible_root);
if (GC_ZVAL_GET_COLOR(zv) != GC_PURPLE) { if (GC_ZVAL_GET_COLOR(zv) != GC_PURPLE) {
GC_ZVAL_SET_PURPLE(zv);
if (!GC_ZVAL_ADDRESS(zv)) { if (!GC_ZVAL_ADDRESS(zv)) {
gc_root_buffer *newRoot = GC_G(unused); gc_root_buffer *newRoot = GC_G(unused);
@ -159,7 +157,6 @@ ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC)
GC_G(first_unused)++; GC_G(first_unused)++;
} else { } else {
if (!GC_G(gc_enabled)) { if (!GC_G(gc_enabled)) {
GC_ZVAL_SET_BLACK(zv);
return; return;
} }
zv->refcount__gc++; zv->refcount__gc++;
@ -169,10 +166,10 @@ ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC)
if (!newRoot) { if (!newRoot) {
return; return;
} }
GC_ZVAL_SET_PURPLE(zv);
GC_G(unused) = newRoot->prev; GC_G(unused) = newRoot->prev;
} }
GC_ZVAL_SET_PURPLE(zv);
newRoot->next = GC_G(roots).next; newRoot->next = GC_G(roots).next;
newRoot->prev = &GC_G(roots); newRoot->prev = &GC_G(roots);
GC_G(roots).next->prev = newRoot; GC_G(roots).next->prev = newRoot;
@ -203,7 +200,6 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj; obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
if (GC_GET_COLOR(obj->buffered) != GC_PURPLE) { if (GC_GET_COLOR(obj->buffered) != GC_PURPLE) {
GC_SET_PURPLE(obj->buffered);
if (!GC_ADDRESS(obj->buffered)) { if (!GC_ADDRESS(obj->buffered)) {
gc_root_buffer *newRoot = GC_G(unused); gc_root_buffer *newRoot = GC_G(unused);
@ -214,7 +210,6 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
GC_G(first_unused)++; GC_G(first_unused)++;
} else { } else {
if (!GC_G(gc_enabled)) { if (!GC_G(gc_enabled)) {
GC_ZVAL_SET_BLACK(zv);
return; return;
} }
zv->refcount__gc++; zv->refcount__gc++;
@ -225,10 +220,10 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
return; return;
} }
obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj; obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
GC_SET_PURPLE(obj->buffered);
GC_G(unused) = newRoot->prev; GC_G(unused) = newRoot->prev;
} }
GC_SET_PURPLE(obj->buffered);
newRoot->next = GC_G(roots).next; newRoot->next = GC_G(roots).next;
newRoot->prev = &GC_G(roots); newRoot->prev = &GC_G(roots);
GC_G(roots).next->prev = newRoot; GC_G(roots).next->prev = newRoot;

View file

@ -1420,6 +1420,7 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
if (error == FAILURE) { if (error == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION");
} else if (retval_ptr) { } else if (retval_ptr) {
_php_curl_verify_handlers(ch, 1 TSRMLS_CC);
if (Z_TYPE_P(retval_ptr) != IS_LONG) { if (Z_TYPE_P(retval_ptr) != IS_LONG) {
convert_to_long_ex(&retval_ptr); convert_to_long_ex(&retval_ptr);
} }
@ -2855,6 +2856,7 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue TSRMLS_DC)
curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share); curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share);
} }
} }
break;
#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
case CURLOPT_FNMATCH_FUNCTION: case CURLOPT_FNMATCH_FUNCTION:

View file

@ -1,10 +1,7 @@
--TEST-- --TEST--
Bug #69316: Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER Bug #69316: Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER
--SKIPIF-- --SKIPIF--
<?php <?php include 'skipif.inc'; ?>
if (!extension_loaded("curl")) exit("skip curl extension not loaded");
if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
?>
--FILE-- --FILE--
<?php <?php
function hdr_callback($ch, $data) { function hdr_callback($ch, $data) {
@ -18,8 +15,9 @@ if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_R
} }
return strlen($data); return strlen($data);
} }
$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
include 'server.inc';
$host = curl_cli_server_start();
$temp_file = dirname(__FILE__) . '/body.tmp'; $temp_file = dirname(__FILE__) . '/body.tmp';
$url = "{$host}/get.php?test=getpost"; $url = "{$host}/get.php?test=getpost";
$ch = curl_init(); $ch = curl_init();

View file

@ -1,5 +1,5 @@
--TEST-- --TEST--
Bug #68799 (Free called on unitialized pointer) Bug #68799 (Free called on uninitialized pointer)
--SKIPIF-- --SKIPIF--
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?> <?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
--FILE-- --FILE--

View file

@ -199,7 +199,6 @@ mysqli_close($link);
if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) { if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
printf("[008] %s [%d] %s\n", $column_def, printf("[008] %s [%d] %s\n", $column_def,
mysqli_errno($link), mysqli_error($link)); mysqli_errno($link), mysqli_error($link));
continue;
} }
$column_def = array('col1 CHAR(1)', 'col2 CHAR(2)','INDEX idx_col1_col2(col1, col2)'); $column_def = array('col1 CHAR(1)', 'col2 CHAR(2)','INDEX idx_col1_col2(col1, col2)');
@ -220,7 +219,6 @@ mysqli_close($link);
while ($field = mysqli_fetch_field($res)) { while ($field = mysqli_fetch_field($res)) {
if (!isset($expected_flags[$field->name])) { if (!isset($expected_flags[$field->name])) {
printf("[010] Found unexpected field '%s'\n", $field->name); printf("[010] Found unexpected field '%s'\n", $field->name);
continue;
} }
list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags[$field->name], $flags); list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags[$field->name], $flags);
if ($unexpected_flags) if ($unexpected_flags)

View file

@ -960,9 +960,9 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC)
charextraalloc = 0; charextraalloc = 0;
colfieldid = SQL_COLUMN_DISPLAY_SIZE; colfieldid = SQL_COLUMN_DISPLAY_SIZE;
rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_NAME, rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), PHP_ODBC_DESC_BASE_COLUMN_NAME,
result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0); result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE, rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE,
NULL, 0, NULL, &result->values[i].coltype); NULL, 0, NULL, &result->values[i].coltype);
/* Don't bind LONG / BINARY columns, so that fetch behaviour can /* Don't bind LONG / BINARY columns, so that fetch behaviour can
@ -997,7 +997,7 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC)
charextraalloc = 1; charextraalloc = 1;
#endif #endif
default: default:
rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), colfieldid, rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), colfieldid,
NULL, 0, NULL, &displaysize); NULL, 0, NULL, &displaysize);
/* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */ /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
if (result->values[i].coltype == SQL_TIMESTAMP) { if (result->values[i].coltype == SQL_TIMESTAMP) {
@ -1091,7 +1091,7 @@ void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
RETURN_FALSE; RETURN_FALSE;
} }
SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len); PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
RETURN_LONG(len); RETURN_LONG(len);
} }
@ -2135,7 +2135,7 @@ PHP_FUNCTION(odbc_result)
fieldsize = result->longreadlen; fieldsize = result->longreadlen;
} }
} else { } else {
SQLColAttributes(result->stmt, (SQLUSMALLINT)(field_ind + 1), PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(field_ind + 1),
(SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH : (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
SQL_COLUMN_DISPLAY_SIZE), SQL_COLUMN_DISPLAY_SIZE),
NULL, 0, NULL, &fieldsize); NULL, 0, NULL, &fieldsize);
@ -2871,7 +2871,7 @@ PHP_FUNCTION(odbc_field_type)
RETURN_FALSE; RETURN_FALSE;
} }
SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL); PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
RETURN_STRING(tmp,1) RETURN_STRING(tmp,1)
} }
/* }}} */ /* }}} */

View file

@ -281,8 +281,16 @@ void odbc_sql_error(ODBC_SQL_ERROR_PARAMS);
#if defined(ODBCVER) && (ODBCVER >= 0x0300) #if defined(ODBCVER) && (ODBCVER >= 0x0300)
#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR || x == SQL_WLONGVARCHAR) #define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR || x == SQL_WLONGVARCHAR)
#define PHP_ODBC_SQLCOLATTRIBUTE SQLColAttribute
#define PHP_ODBC_DESC_BASE_COLUMN_NAME SQL_DESC_BASE_COLUMN_NAME
#else #else
#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR) #define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR)
#define PHP_ODBC_SQLCOLATTRIBUTE SQLColAttributes
#define PHP_ODBC_DESC_BASE_COLUMN_NAME SQL_COLUMN_NAME
#endif #endif
#define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY) #define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY)

View file

@ -2,6 +2,11 @@
odbc_exec(): Getting accurate unicode data from query odbc_exec(): Getting accurate unicode data from query
--SKIPIF-- --SKIPIF--
<?php include 'skipif.inc'; ?> <?php include 'skipif.inc'; ?>
<?php
if ("unixODBC" != ODBC_TYPE) {
die("skip ODBC_TYPE != unixODBC");
}
?>
--FILE-- --FILE--
<?php <?php

View file

@ -0,0 +1,43 @@
--TEST--
Bug #69354 Incorrect use of SQLColAttributes with ODBC 3.0
--SKIPIF--
<?php include 'skipif.inc'; ?>
--FILE--
<?php
include 'config.inc';
$conn = odbc_connect($dsn, $user, $pass);
@odbc_exec($conn, 'CREATE DATABASE odbcTEST');
odbc_exec($conn, 'CREATE TABLE FOO (ID INT, VARCHAR_COL VARCHAR(100))');
odbc_exec($conn, "INSERT INTO FOO(ID, VARCHAR_COL) VALUES (1, '" . str_repeat("a", 100) . "')");
$res = odbc_exec($conn,"select VARCHAR_COL from FOO");
if ($res) {
if (odbc_fetch_row($res)) {
$ret = odbc_result($res,'varchar_col');
echo strlen($ret), "\n";
echo $ret[0], "\n";
echo $ret[strlen($ret)-1], "\n";
}
}
?>
==DONE==
--EXPECT--
100
a
a
==DONE==
--CLEAN--
<?php
include 'config.inc';
$conn = odbc_connect($dsn, $user, $pass);
odbc_exec($conn, 'DROP TABLE FOO');
odbc_exec($conn, 'DROP DATABASE odbcTEST');
?>

View file

@ -2,6 +2,11 @@
odbc_exec(): Basic test odbc_exec(): Basic test
--SKIPIF-- --SKIPIF--
<?php include 'skipif.inc'; ?> <?php include 'skipif.inc'; ?>
<?php
if ("unixODBC" != ODBC_TYPE) {
die("skip ODBC_TYPE != unixODBC");
}
?>
--FILE-- --FILE--
<?php <?php

View file

@ -11,7 +11,7 @@ $conn = odbc_connect($dsn, $user, $pass);
odbc_exec($conn, 'CREATE DATABASE odbcTEST'); odbc_exec($conn, 'CREATE DATABASE odbcTEST');
odbc_exec($conn, 'CREATE TABLE FOO (TEST INT)'); odbc_exec($conn, 'CREATE TABLE FOO (TEST INT NOT NULL)');
odbc_exec($conn, 'ALTER TABLE FOO ADD PRIMARY KEY (TEST)'); odbc_exec($conn, 'ALTER TABLE FOO ADD PRIMARY KEY (TEST)');
odbc_exec($conn, 'INSERT INTO FOO VALUES (1)'); odbc_exec($conn, 'INSERT INTO FOO VALUES (1)');

View file

@ -0,0 +1,17 @@
--TEST--
Test that script cached info is correct with validate_timestamps disabled
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.validate_timestamps=0
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
var_dump(opcache_is_script_cached(__FILE__));
var_dump(opcache_is_script_cached("nonexistent.php"));
?>
--EXPECT--
bool(true)
bool(false)

View file

@ -4,6 +4,7 @@ Test that script cached info is correct
opcache.enable=1 opcache.enable=1
opcache.enable_cli=1 opcache.enable_cli=1
opcache.file_update_protection=0 opcache.file_update_protection=0
opcache.validate_timestamps=1
--SKIPIF-- --SKIPIF--
<?php require_once('skipif.inc'); ?> <?php require_once('skipif.inc'); ?>
--FILE-- --FILE--

View file

@ -320,14 +320,16 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC)
persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len + 1); persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len + 1);
if (persistent_script) { if (persistent_script) {
return !persistent_script->corrupted && return !persistent_script->corrupted &&
validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS; (!ZCG(accel_directives).validate_timestamps ||
validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS);
} }
} }
if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) { if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) {
persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1); persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1);
return persistent_script && !persistent_script->corrupted && return persistent_script && !persistent_script->corrupted &&
validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS; (!ZCG(accel_directives).validate_timestamps ||
validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS);
} }
return 0; return 0;

View file

@ -346,10 +346,10 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML
retval = ZCG(mem);; retval = ZCG(mem);;
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
memcpy(retval, source, size); memcpy(retval, source, size);
zend_shared_alloc_register_xlat_entry(source, retval);
if (free_source) { if (free_source) {
interned_efree((char*)source); interned_efree((char*)source);
} }
zend_shared_alloc_register_xlat_entry(source, retval);
return retval; return retval;
} }

View file

@ -688,7 +688,7 @@ the alternative names that are used. */
#define foc number #define foc number
#define save_mark data #define save_mark data
/* These statements are here to stop the compiler complaining about unitialized /* These statements are here to stop the compiler complaining about uninitialized
variables. */ variables. */
#ifdef SUPPORT_UCP #ifdef SUPPORT_UCP

View file

@ -85,10 +85,12 @@ MySQLPDOTest::skip();
} catch (PDOException $e) { } catch (PDOException $e) {
printf("[001] %s, [%s] %s\n", printf("[001] %s, [%s] %s [%s] %s\n",
$e->getMessage(), $e->getMessage(),
(is_object($db)) ? $db->errorCode() : 'n/a', (is_object($db1)) ? $db1->errorCode() : 'n/a',
(is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); (is_object($db1)) ? implode(' ', $db1->errorInfo()) : 'n/a',
(is_object($db2)) ? $db2->errorCode() : 'n/a',
(is_object($db2)) ? implode(' ', $db2->errorInfo()) : 'n/a');
} }
print "done!"; print "done!";

View file

@ -113,7 +113,7 @@ static void xmlwriter_free_resource_ptr(xmlwriter_object *intern TSRMLS_DC)
ze_xmlwriter_object *obj = (ze_xmlwriter_object*) zend_object_store_get_object(object TSRMLS_CC); \ ze_xmlwriter_object *obj = (ze_xmlwriter_object*) zend_object_store_get_object(object TSRMLS_CC); \
intern = obj->xmlwriter_ptr; \ intern = obj->xmlwriter_ptr; \
if (!intern) { \ if (!intern) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized XMLWriter object"); \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized XMLWriter object"); \
RETURN_FALSE; \ RETURN_FALSE; \
} \ } \
} }

View file

@ -417,7 +417,7 @@ static int php_zip_parse_options(zval *options, long *remove_all_path,
ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \ ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
intern = obj->za; \ intern = obj->za; \
if (!intern) { \ if (!intern) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized Zip object"); \
RETURN_FALSE; \ RETURN_FALSE; \
} \ } \
} }