Merge remote-tracking branch 'origin/master' into native-tls

* origin/master: (25 commits)
  Fix return code (merges are hard :( )
  fix bad merge
  Fix bug #68113 (Heap corruption in exif_thumbnail())
  Fix bug #68089 - do not accept options with embedded \0
  Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
  Fix bug #68027 - fix date parsing in XMLRPC lib
  Fix bug #68113 (Heap corruption in exif_thumbnail())
  Fix bug #68089 - do not accept options with embedded \0
  Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
  Fix bug #68027 - fix date parsing in XMLRPC lib
  Fix bug #68113 (Heap corruption in exif_thumbnail())
  Fix bug #68089 - do not accept options with embedded \0
  Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
  Fix bug #68027 - fix date parsing in XMLRPC lib
  Fixed bug #68128
  Added API function to retrive current custom heap handlers
  update NEWS and UPGRADING
  Allow to substitute storage layer in memory manager.
  Upated NEWS
  Address issues raised by @nikic
  ...
This commit is contained in:
Anatol Belski 2014-10-15 08:32:54 +02:00
commit 382f95e612
24 changed files with 686 additions and 317 deletions

View file

@ -119,6 +119,9 @@
# define ZEND_MM_CUSTOM 1 /* support for custom memory allocator */
/* USE_ZEND_ALLOC=0 may switch to system malloc() */
#endif
#ifndef ZEND_MM_STORAGE
# define ZEND_MM_STORAGE 1 /* support for custom memory storage */
#endif
#ifndef ZEND_MM_ERROR
# define ZEND_MM_ERROR 1 /* report system errors */
#endif
@ -217,6 +220,9 @@ struct _zend_mm_heap {
#if ZEND_MM_CUSTOM
int use_custom_heap;
#endif
#if ZEND_MM_STORAGE
zend_mm_storage *storage;
#endif
#if ZEND_MM_STAT
size_t size; /* current memory usage */
size_t peak; /* peak memory usage */
@ -707,7 +713,7 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse
/* Chunks */
/**********/
static void *zend_mm_chunk_alloc(size_t size, size_t alignment)
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
{
void *ptr = zend_mm_mmap(size);
@ -751,6 +757,40 @@ static void *zend_mm_chunk_alloc(size_t size, size_t alignment)
}
}
static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment)
{
#if ZEND_MM_STORAGE
if (UNEXPECTED(heap->storage)) {
void *ptr = heap->storage->chunk_alloc(heap->storage, size, alignment);
ZEND_ASSERT(((zend_uintptr_t)((char*)ptr + (alignment-1)) & (alignment-1)) == (zend_uintptr_t)ptr);
return ptr;
}
#endif
return zend_mm_chunk_alloc_int(size, alignment);
}
static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size)
{
#if ZEND_MM_STORAGE
if (UNEXPECTED(heap->storage)) {
heap->storage->chunk_free(heap->storage, addr, size);
return;
}
#endif
zend_mm_munmap(addr, size);
}
static void zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size)
{
#if ZEND_MM_STORAGE
if (UNEXPECTED(heap->storage)) {
heap->storage->chunk_truncate(heap->storage, addr, old_size, new_size);
return;
}
#endif
zend_mm_munmap((char*)addr + new_size, old_size - new_size);
}
static zend_always_inline void zend_mm_chunk_init(zend_mm_heap *heap, zend_mm_chunk *chunk)
{
chunk->heap = heap;
@ -928,7 +968,7 @@ not_found:
}
}
#endif
chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(heap, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
if (UNEXPECTED(chunk == NULL)) {
/* insufficient memory */
#if !ZEND_MM_LIMIT
@ -1019,11 +1059,11 @@ static void zend_mm_free_pages(zend_mm_heap *heap, zend_mm_chunk *chunk, int pag
heap->real_size -= ZEND_MM_CHUNK_SIZE;
#endif
if (!heap->cached_chunks || chunk->num > heap->cached_chunks->num) {
zend_mm_munmap(chunk, ZEND_MM_CHUNK_SIZE);
zend_mm_chunk_free(heap, chunk, ZEND_MM_CHUNK_SIZE);
} else {
//TODO: select the best chunk to delete???
chunk->next = heap->cached_chunks->next;
zend_mm_munmap(heap->cached_chunks, ZEND_MM_CHUNK_SIZE);
zend_mm_chunk_free(heap, heap->cached_chunks, ZEND_MM_CHUNK_SIZE);
heap->cached_chunks = chunk;
}
}
@ -1355,7 +1395,7 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN
#ifndef _WIN32
} else if (new_size < old_size) {
/* unmup tail */
zend_mm_munmap((char*)ptr + new_size, old_size - new_size);
zend_mm_chunk_truncate(heap, ptr, old_size, new_size);
#if ZEND_MM_STAT || ZEND_MM_LIMIT
heap->real_size -= old_size - new_size;
#endif
@ -1607,7 +1647,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
}
}
#endif
ptr = zend_mm_chunk_alloc(new_size, ZEND_MM_CHUNK_SIZE);
ptr = zend_mm_chunk_alloc(heap, new_size, ZEND_MM_CHUNK_SIZE);
if (UNEXPECTED(ptr == NULL)) {
/* insufficient memory */
#if !ZEND_MM_LIMIT
@ -1649,7 +1689,7 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE) == 0, "zend_mm_heap corrupted");
size = zend_mm_del_huge_block(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
zend_mm_munmap(ptr, size);
zend_mm_chunk_free(heap, ptr, size);
#if ZEND_MM_STAT || ZEND_MM_LIMIT
heap->real_size -= size;
#endif
@ -1662,9 +1702,9 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
/* Initialization */
/******************/
zend_mm_heap *zend_mm_init(void)
static zend_mm_heap *zend_mm_init(void)
{
zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
zend_mm_heap *heap;
if (UNEXPECTED(chunk == NULL)) {
@ -1706,6 +1746,9 @@ zend_mm_heap *zend_mm_init(void)
#endif
#if ZEND_MM_CUSTOM
heap->use_custom_heap = 0;
#endif
#if ZEND_MM_STORAGE
heap->storage = NULL;
#endif
heap->huge_list = NULL;
return heap;
@ -1805,7 +1848,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC)
}
list = list->next;
zend_mm_munmap(q->ptr, q->size);
zend_mm_chunk_free(heap, q->ptr, q->size);
zend_mm_free_heap(heap, q, NULL, 0, NULL, 0);
}
@ -1904,7 +1947,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
while (list) {
zend_mm_huge_list *q = list;
list = list->next;
zend_mm_munmap(q->ptr, q->size);
zend_mm_chunk_free(heap, q->ptr, q->size);
}
/* move all chunks except of the first one into the cache */
@ -1923,10 +1966,20 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
while (heap->cached_chunks) {
p = heap->cached_chunks;
heap->cached_chunks = p->next;
zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE);
}
/* free the first chunk */
zend_mm_munmap(heap->main_chunk, ZEND_MM_CHUNK_SIZE);
#if ZEND_MM_STORAGE
if (UNEXPECTED(heap->storage)) {
zend_mm_storage *storage = heap->storage;
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
storage->dtor(storage);
} else {
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
}
#else
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
#endif
} else {
zend_mm_heap old_heap;
@ -1936,7 +1989,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
heap->cached_chunks) {
p = heap->cached_chunks;
heap->cached_chunks = p->next;
zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE);
heap->cached_chunks_count--;
}
/* clear cached chunks */
@ -2343,6 +2396,98 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
#endif
}
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
void* (**_malloc)(size_t),
void (**_free)(void*),
void* (**_realloc)(void*, size_t))
{
#if ZEND_MM_CUSTOM
zend_mm_heap *_heap = (zend_mm_heap*)heap;
if (heap->use_custom_heap) {
*_malloc = _heap->_malloc;
*_free = _heap->_free;
*_realloc = _heap->_realloc;
} else {
*_malloc = NULL;
*_free = NULL;
*_realloc = NULL;
}
#else
*_malloc = NULL;
*_free = NULL;
*_realloc = NULL;
#endif
}
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
{
#if ZEND_MM_CUSTOM
return heap->storage;
#else
return NULL
#endif
}
ZEND_API zend_mm_heap *zend_mm_startup(void)
{
return zend_mm_init();
}
ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage)
{
#if ZEND_MM_STORAGE
zend_mm_chunk *chunk = (zend_mm_chunk*)storage->chunk_alloc(storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
zend_mm_heap *heap;
if (UNEXPECTED(chunk == NULL)) {
#if ZEND_MM_ERROR
#ifdef _WIN32
stderr_last_error("Can't initialize heap");
#else
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
#endif
#endif
return NULL;
}
heap = &chunk->heap_slot;
chunk->heap = heap;
chunk->next = chunk;
chunk->prev = chunk;
chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
chunk->free_tail = ZEND_MM_FIRST_PAGE;
chunk->num = 0;
chunk->free_map[0] = (Z_L(1) << ZEND_MM_FIRST_PAGE) - 1;
chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE);
heap->main_chunk = chunk;
heap->cached_chunks = NULL;
heap->chunks_count = 1;
heap->peak_chunks_count = 1;
heap->cached_chunks_count = 0;
heap->avg_chunks_count = 1.0;
#if ZEND_MM_STAT || ZEND_MM_LIMIT
heap->real_size = ZEND_MM_CHUNK_SIZE;
#endif
#if ZEND_MM_STAT
heap->real_peak = ZEND_MM_CHUNK_SIZE;
heap->size = 0;
heap->peak = 0;
#endif
#if ZEND_MM_LIMIT
heap->limit = (Z_L(-1) >> Z_L(1));
heap->overflow = 0;
#endif
#if ZEND_MM_CUSTOM
heap->use_custom_heap = 0;
#endif
heap->storage = storage;
heap->huge_list = NULL;
return heap;
#else
return NULL;
#endif
}
/*
* Local variables:
* tab-width: 4

View file

@ -259,6 +259,27 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
void* (*_malloc)(size_t),
void (*_free)(void*),
void* (*_realloc)(void*, size_t));
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
void* (**_malloc)(size_t),
void (**_free)(void*),
void* (**_realloc)(void*, size_t));
typedef struct _zend_mm_storage zend_mm_storage;
typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment);
typedef void (*zend_mm_chunk_free_t)(zend_mm_storage *storage, void *chunk, size_t size);
typedef void (*zend_mm_chunk_truncate_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size);
typedef void (*zend_mm_storage_dtor_t)(zend_mm_storage *storage);
struct _zend_mm_storage {
zend_mm_chunk_alloc_t chunk_alloc;
zend_mm_chunk_free_t chunk_free;
zend_mm_chunk_truncate_t chunk_truncate;
zend_mm_storage_dtor_t dtor;
};
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap);
ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage);
END_EXTERN_C()

View file

@ -170,6 +170,11 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str,
{
CURLcode error = CURLE_OK;
if (strlen(str) != len) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Curl option contains invalid characters (\\0)");
return FAILURE;
}
#if LIBCURL_VERSION_NUM >= 0x071100
if (make_copy) {
#endif

View file

@ -0,0 +1,18 @@
--TEST--
Bug #68089 (NULL byte injection - cURL lib)
--SKIPIF--
<?php
include 'skipif.inc';
?>
--FILE--
<?php
$url = "file:///etc/passwd\0http://google.com";
$ch = curl_init();
var_dump(curl_setopt($ch, CURLOPT_URL, $url));
?>
Done
--EXPECTF--
Warning: curl_setopt(): Curl option contains invalid characters (\0) in %s/bug68089.php on line 4
bool(false)
Done

View file

@ -2413,11 +2413,11 @@ static void* exif_ifd_make_value(image_info_data *info_data, int motorola_intel
data_ptr += 8;
break;
case TAG_FMT_SINGLE:
memmove(data_ptr, &info_data->value.f, byte_count);
memmove(data_ptr, &info_value->f, 4);
data_ptr += 4;
break;
case TAG_FMT_DOUBLE:
memmove(data_ptr, &info_data->value.d, byte_count);
memmove(data_ptr, &info_value->d, 8);
data_ptr += 8;
break;
}

BIN
ext/exif/tests/bug68113.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

View file

@ -0,0 +1,17 @@
--TEST--
Bug #68113 (Heap corruption in exif_thumbnail())
--SKIPIF--
<?php
extension_loaded("exif") or die("skip need exif");
?>
--FILE--
<?php
var_dump(exif_thumbnail(__DIR__."/bug68113.jpg"));
?>
Done
--EXPECTF--
Warning: exif_thumbnail(bug68113.jpg): File structure corrupted in %s/bug68113.php on line 2
Warning: exif_thumbnail(bug68113.jpg): Invalid JPEG file in %s/bug68113.php on line 2
bool(false)
Done

View file

@ -104,6 +104,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0)
ZEND_ARG_INFO(0, limiter)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_bits, 0, 0, 1)
ZEND_ARG_INFO(0, bits)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_range, 0, 0, 2)
ZEND_ARG_INFO(0, min)
ZEND_ARG_INFO(0, max)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2)
ZEND_ARG_INFO(0, a)
ZEND_ARG_INFO(0, index)
@ -161,6 +170,8 @@ const zend_function_entry gmp_functions[] = {
ZEND_FE(gmp_cmp, arginfo_gmp_binary)
ZEND_FE(gmp_sign, arginfo_gmp_unary)
ZEND_FE(gmp_random, arginfo_gmp_random)
ZEND_FE(gmp_random_bits, arginfo_gmp_random_bits)
ZEND_FE(gmp_random_range, arginfo_gmp_random_range)
ZEND_FE(gmp_and, arginfo_gmp_binary)
ZEND_FE(gmp_or, arginfo_gmp_binary)
ZEND_FE(gmp_com, arginfo_gmp_unary)
@ -1743,6 +1754,18 @@ ZEND_FUNCTION(gmp_sign)
}
/* }}} */
static void gmp_init_random(TSRMLS_D)
{
if (!GMPG(rand_initialized)) {
/* Initialize */
gmp_randinit_mt(GMPG(rand_state));
/* Seed */
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
GMPG(rand_initialized) = 1;
}
}
/* {{{ proto GMP gmp_random([int limiter])
Gets random number */
ZEND_FUNCTION(gmp_random)
@ -1755,16 +1778,8 @@ ZEND_FUNCTION(gmp_random)
}
INIT_GMP_RETVAL(gmpnum_result);
gmp_init_random(TSRMLS_C);
if (!GMPG(rand_initialized)) {
/* Initialize */
gmp_randinit_mt(GMPG(rand_state));
/* Seed */
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
GMPG(rand_initialized) = 1;
}
#ifdef GMP_LIMB_BITS
mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
#else
@ -1773,6 +1788,91 @@ ZEND_FUNCTION(gmp_random)
}
/* }}} */
/* {{{ proto GMP gmp_random_bits(int bits)
Gets a random number in the range 0 to (2 ** n) - 1 */
ZEND_FUNCTION(gmp_random_bits)
{
long bits;
mpz_ptr gmpnum_result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bits) == FAILURE) {
return;
}
if (bits <= 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The number of bits must be positive");
RETURN_FALSE;
}
INIT_GMP_RETVAL(gmpnum_result);
gmp_init_random(TSRMLS_C);
mpz_urandomb(gmpnum_result, GMPG(rand_state), bits);
}
/* }}} */
/* {{{ proto GMP gmp_random_range(mixed min, mixed max)
Gets a random number in the range min to max */
ZEND_FUNCTION(gmp_random_range)
{
zval *min_arg, *max_arg;
mpz_ptr gmpnum_min, gmpnum_max, gmpnum_result;
gmp_temp_t temp_a, temp_b;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &min_arg, &max_arg) == FAILURE) {
return;
}
gmp_init_random(TSRMLS_C);
FETCH_GMP_ZVAL(gmpnum_max, max_arg, temp_a);
if (Z_TYPE_P(min_arg) == IS_LONG && Z_LVAL_P(min_arg) >= 0) {
if (mpz_cmp_ui(gmpnum_max, Z_LVAL_P(min_arg)) <= 0) {
FREE_GMP_TEMP(temp_a);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
RETURN_FALSE;
}
INIT_GMP_RETVAL(gmpnum_result);
if (Z_LVAL_P(min_arg)) {
mpz_sub_ui(gmpnum_max, gmpnum_max, Z_LVAL_P(min_arg));
}
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
if (Z_LVAL_P(min_arg)) {
mpz_add_ui(gmpnum_result, gmpnum_result, Z_LVAL_P(min_arg));
}
FREE_GMP_TEMP(temp_a);
}
else {
FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a);
if (mpz_cmp(gmpnum_max, gmpnum_min) <= 0) {
FREE_GMP_TEMP(temp_b);
FREE_GMP_TEMP(temp_a);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
RETURN_FALSE;
}
INIT_GMP_RETVAL(gmpnum_result);
mpz_sub(gmpnum_max, gmpnum_max, gmpnum_min);
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
mpz_add(gmpnum_result, gmpnum_result, gmpnum_min);
FREE_GMP_TEMP(temp_b);
FREE_GMP_TEMP(temp_a);
}
}
/* }}} */
/* {{{ proto GMP gmp_and(mixed a, mixed b)
Calculates logical AND of a and b */
ZEND_FUNCTION(gmp_and)

View file

@ -66,6 +66,8 @@ ZEND_FUNCTION(gmp_or);
ZEND_FUNCTION(gmp_com);
ZEND_FUNCTION(gmp_xor);
ZEND_FUNCTION(gmp_random);
ZEND_FUNCTION(gmp_random_bits);
ZEND_FUNCTION(gmp_random_range);
ZEND_FUNCTION(gmp_setbit);
ZEND_FUNCTION(gmp_clrbit);
ZEND_FUNCTION(gmp_scan0);

View file

@ -0,0 +1,45 @@
--TEST--
gmp_random_bits() basic tests
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
--FILE--
<?php
var_dump(gmp_random_bits());
var_dump(gmp_random_bits(0));
var_dump(gmp_random_bits(-1));
// If these error the test fails.
gmp_random_bits(1);
gmp_random_bits(1024);
// 2 seconds to make sure the numbers stay in range
$start = microtime(true);
$limit = (2 ** 30) - 1;
while (1) {
for ($i = 0; $i < 5000; $i++) {
$result = gmp_random_bits(30);
if ($result < 0 || $result > $limit) {
print "RANGE VIOLATION\n";
var_dump($result);
break 2;
}
}
if (microtime(true) - $start > 2) {
break;
}
}
echo "Done\n";
?>
--EXPECTF--
Warning: gmp_random_bits() expects exactly 1 parameter, 0 given in %s on line %d
NULL
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
bool(false)
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
bool(false)
Done

View file

@ -0,0 +1,81 @@
--TEST--
gmp_random_range() basic tests
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
--FILE--
<?php
$minusTen = gmp_init(-1);
$plusTen = gmp_init(1);
$zero = gmp_init(0);
var_dump(gmp_random_range());
var_dump(gmp_random_range(10));
var_dump(gmp_random_range(10, -10));
var_dump(gmp_random_range($plusTen, $minusTen));
var_dump(gmp_random_range($plusTen, $zero));
// If these error the test fails.
gmp_random_range(0, 10);
gmp_random_range(1, 10);
gmp_random_range(-1, 10);
gmp_random_range(-10, 0);
gmp_random_range(-10, -1);
gmp_random_range(0, $plusTen);
gmp_random_range(1, $plusTen);
gmp_random_range(-1, $plusTen);
gmp_random_range($zero, $plusTen);
gmp_random_range($minusTen, $plusTen);
// 2 seconds to make sure the numbers stay in range
$start = microtime(true);
while (1) {
for ($i = 0; $i < 5000; $i++) {
$result = gmp_random_range(0, 1000);
if ($result < 0 || $result > 1000) {
print "RANGE VIOLATION 1\n";
var_dump($result);
break 2;
}
$result = gmp_random_range(-1000, 0);
if ($result < -1000 || $result > 0) {
print "RANGE VIOLATION 2\n";
var_dump($result);
break 2;
}
$result = gmp_random_range(-500, 500);
if ($result < -500 || $result > 500) {
print "RANGE VIOLATION 3\n";
var_dump($result);
break 2;
}
}
if (microtime(true) - $start > 2) {
break;
}
}
echo "Done\n";
?>
--EXPECTF--
Warning: gmp_random_range() expects exactly 2 parameters, 0 given in %s on line %d
NULL
Warning: gmp_random_range() expects exactly 2 parameters, 1 given in %s on line %d
NULL
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
bool(false)
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
bool(false)
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
bool(false)
Done

View file

@ -51,6 +51,36 @@ static inline int spl_instantiate_arg_ex2(zend_class_entry *pce, zval *retval, z
}
/* }}} */
/* {{{ spl_instantiate_arg_n */
static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval *retval, int argc, zval *argv TSRMLS_DC)
{
zend_function *func = pce->constructor;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval dummy;
spl_instantiate(pce, retval TSRMLS_CC);
fci.size = sizeof(zend_fcall_info);
fci.function_table = &pce->function_table;
ZVAL_STR(&fci.function_name, func->common.function_name);
fci.object = Z_OBJ_P(retval);
fci.symbol_table = NULL;
fci.retval = &dummy;
fci.param_count = argc;
fci.params = argv;
fci.no_separation = 1;
fcc.initialized = 1;
fcc.function_handler = func;
fcc.calling_scope = EG(scope);
fcc.called_scope = pce;
fcc.object = Z_OBJ_P(retval);
zend_call_function(&fci, &fcc TSRMLS_CC);
}
/* }}} */
#endif /* SPL_ENGINE_H */
/*

View file

@ -2037,8 +2037,10 @@ SPL_METHOD(RegexIterator, accept)
if (Z_TYPE(intern->current.data) == IS_UNDEF) {
RETURN_FALSE;
} else if (Z_TYPE(intern->current.data) == IS_ARRAY) {
RETURN_FALSE;
}
if (intern->u.regex.flags & REGIT_USE_KEY) {
subject_ptr = &intern->current.key;
} else {
@ -2074,8 +2076,7 @@ SPL_METHOD(RegexIterator, accept)
ZVAL_UNDEF(&intern->current.data);
php_pcre_match_impl(intern->u.regex.pce, subject, subject_len, &zcount,
&intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0 TSRMLS_CC);
count = zend_hash_num_elements(Z_ARRVAL(intern->current.data));
RETVAL_BOOL(count > 0);
RETVAL_BOOL(Z_LVAL(zcount) > 0);
break;
case REGIT_MODE_SPLIT:
@ -2254,7 +2255,7 @@ SPL_METHOD(RecursiveRegexIterator, __construct)
SPL_METHOD(RecursiveRegexIterator, getChildren)
{
spl_dual_it_object *intern;
zval retval, regex;
zval retval;
if (zend_parse_parameters_none() == FAILURE) {
return;
@ -2264,13 +2265,40 @@ SPL_METHOD(RecursiveRegexIterator, getChildren)
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
if (!EG(exception)) {
ZVAL_STR_COPY(&regex, intern->u.regex.regex);
spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &retval, &regex TSRMLS_CC);
zval_ptr_dtor(&regex);
zval args[5];
ZVAL_COPY(&args[0], &retval);
ZVAL_STR_COPY(&args[1], intern->u.regex.regex);
ZVAL_LONG(&args[2], intern->u.regex.mode);
ZVAL_LONG(&args[3], intern->u.regex.flags);
ZVAL_LONG(&args[4], intern->u.regex.preg_flags);
spl_instantiate_arg_n(Z_OBJCE_P(getThis()), return_value, 5, args TSRMLS_CC);
zval_ptr_dtor(&args[1]);
}
zval_ptr_dtor(&retval);
} /* }}} */
SPL_METHOD(RecursiveRegexIterator, accept)
{
spl_dual_it_object *intern;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
if (Z_TYPE(intern->current.data) == IS_UNDEF) {
RETURN_FALSE;
} else if (Z_TYPE(intern->current.data) == IS_ARRAY) {
RETURN_BOOL(zend_hash_num_elements(Z_ARRVAL(intern->current.data)) > 0);
}
zend_call_method_with_0_params(getThis(), spl_ce_RegexIterator, NULL, "accept", return_value);
}
#endif
/* {{{ spl_dual_it_dtor */
@ -2456,6 +2484,7 @@ ZEND_END_ARG_INFO();
static const zend_function_entry spl_funcs_RecursiveRegexIterator[] = {
SPL_ME(RecursiveRegexIterator, __construct, arginfo_rec_regex_it___construct, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveRegexIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveRegexIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
PHP_FE_END

View file

@ -0,0 +1,91 @@
--TEST--
Bug #68128 - RecursiveRegexIterator raises "Array to string conversion" notice
--FILE--
<?php
$array = new ArrayIterator(array('a', array('b', 'c')));
$regex = new RegexIterator($array, '/Array/');
foreach ($regex as $match) {
var_dump($match);
}
$rArrayIterator = new RecursiveArrayIterator(array('test1', array('tet3', 'test4', 'test5')));
$rRegexIterator = new RecursiveRegexIterator($rArrayIterator, '/^(t)est(\d*)/',
RecursiveRegexIterator::ALL_MATCHES, 0, PREG_PATTERN_ORDER);
foreach ($rRegexIterator as $key1 => $value1) {
if ($rRegexIterator->hasChildren()) {
// print all children
echo "Children: ";
foreach ($rRegexIterator->getChildren() as $key => $value) {
print_r($value);
}
echo "\n";
} else {
echo "No children ";
print_r($value1);
echo "\n";
}
}
?>
--EXPECT--
No children Array
(
[0] => Array
(
[0] => test1
)
[1] => Array
(
[0] => t
)
[2] => Array
(
[0] => 1
)
)
Children: Array
(
[0] => Array
(
[0] => test4
)
[1] => Array
(
[0] => t
)
[2] => Array
(
[0] => 4
)
)
Array
(
[0] => Array
(
[0] => test5
)
[1] => Array
(
[0] => t
)
[2] => Array
(
[0] => 5
)
)

View file

@ -13,11 +13,6 @@ class MyRecursiveRegexIterator extends RecursiveRegexIterator
var_dump($v);
}
}
function accept()
{
return $this->hasChildren() || parent::accept();
}
}
$ar = new RecursiveArrayIterator(array('Foo', array('Bar'), 'FooBar', array('Baz'), 'Biz'));

View file

@ -46,8 +46,6 @@ array(3) {
[2]=>
%s(1) "2"
}
Notice: Array to string conversion in %siterator_050.php on line %d
int(0)
array(2) {
[0]=>
@ -69,8 +67,6 @@ array(2) {
[1]=>
%s(1) "1"
}
Notice: Array to string conversion in %siterator_050.php on line %d
object(ArrayIterator)#%d (1) {
%s"storage"%s"ArrayIterator":private]=>
array(9) {

View file

@ -46,18 +46,6 @@ var_dump($ar);
<?php exit(0); ?>
--EXPECTF--
bool(true)
int(0)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(1)
array(3) {
@ -97,85 +85,11 @@ array(3) {
}
}
bool(true)
int(3)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(4)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
Notice: Array to string conversion in %siterator_052.php on line %d
bool(false)
bool(true)
int(5)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(6)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(7)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(8)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(0)
array(2) {
@ -231,67 +145,11 @@ array(2) {
}
}
bool(true)
int(3)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
bool(true)
int(4)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
Notice: Array to string conversion in %siterator_052.php on line %d
bool(false)
bool(true)
int(5)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
bool(true)
int(6)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
bool(true)
int(7)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
bool(true)
int(8)
array(2) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
}
object(ArrayIterator)#%d (1) {
["storage":"ArrayIterator":private]=>
array(9) {

View file

@ -46,122 +46,14 @@ var_dump($ar);
<?php exit(0); ?>
--EXPECTF--
bool(true)
int(0)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(1)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(2)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(3)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(4)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(false)
bool(true)
int(5)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(6)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(7)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(8)
array(3) {
[0]=>
array(0) {
}
[1]=>
array(0) {
}
[2]=>
array(0) {
}
}
bool(true)
int(0)
array(2) {
@ -232,20 +124,7 @@ array(2) {
string(1) "4"
}
}
bool(true)
int(5)
array(2) {
[0]=>
array(1) {
[0]=>
string(1) "5"
}
[1]=>
array(1) {
[0]=>
string(1) "5"
}
}
bool(false)
bool(true)
int(6)
array(2) {

View file

@ -42,8 +42,6 @@ array(3) {
[2]=>
string(1) "3"
}
Notice: Array to string conversion in %siterator_054.php on line %d
int(7)
array(2) {
[0]=>

View file

@ -0,0 +1,12 @@
--TEST--
Bug #68044 Integer overflow in unserialize() (32-bits only)
--FILE--
<?php
echo unserialize('C:3:"XYZ":18446744075857035259:{}');
?>
===DONE==
--EXPECTF--
Warning: Insufficient data for unserializing - %d required, 1 present in %s/bug68044.php on line 2
Notice: unserialize(): Error at offset 32 of 33 bytes in %s/bug68044.php on line 2
===DONE==

View file

@ -386,7 +386,7 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
(*p) += 2;
if (datalen < 0 || (*p) + datalen >= max) {
if (datalen < 0 || (max - (*p)) <= datalen) {
zend_error(E_WARNING, "Insufficient data for unserializing - %pd required, %pd present", datalen, (zend_long)(max - (*p)));
return 0;
}

View file

@ -390,7 +390,7 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
(*p) += 2;
if (datalen < 0 || (*p) + datalen >= max) {
if (datalen < 0 || (max - (*p)) <= datalen) {
zend_error(E_WARNING, "Insufficient data for unserializing - %pd required, %pd present", datalen, (zend_long)(max - (*p)));
return 0;
}

View file

@ -219,16 +219,19 @@ static int date_from_ISO8601 (const char *text, time_t * value) {
n = 10;
tm.tm_mon = 0;
for(i = 0; i < 2; i++) {
XMLRPC_IS_NUMBER(text[i])
XMLRPC_IS_NUMBER(text[i+4])
tm.tm_mon += (text[i+4]-'0')*n;
n /= 10;
}
tm.tm_mon --;
if(tm.tm_mon < 0 || tm.tm_mon > 11) {
return -1;
}
n = 10;
tm.tm_mday = 0;
for(i = 0; i < 2; i++) {
XMLRPC_IS_NUMBER(text[i])
XMLRPC_IS_NUMBER(text[i+6])
tm.tm_mday += (text[i+6]-'0')*n;
n /= 10;
}
@ -236,7 +239,7 @@ static int date_from_ISO8601 (const char *text, time_t * value) {
n = 10;
tm.tm_hour = 0;
for(i = 0; i < 2; i++) {
XMLRPC_IS_NUMBER(text[i])
XMLRPC_IS_NUMBER(text[i+9])
tm.tm_hour += (text[i+9]-'0')*n;
n /= 10;
}
@ -244,7 +247,7 @@ static int date_from_ISO8601 (const char *text, time_t * value) {
n = 10;
tm.tm_min = 0;
for(i = 0; i < 2; i++) {
XMLRPC_IS_NUMBER(text[i])
XMLRPC_IS_NUMBER(text[i+12])
tm.tm_min += (text[i+12]-'0')*n;
n /= 10;
}
@ -252,7 +255,7 @@ static int date_from_ISO8601 (const char *text, time_t * value) {
n = 10;
tm.tm_sec = 0;
for(i = 0; i < 2; i++) {
XMLRPC_IS_NUMBER(text[i])
XMLRPC_IS_NUMBER(text[i+15])
tm.tm_sec += (text[i+15]-'0')*n;
n /= 10;
}

View file

@ -0,0 +1,44 @@
--TEST--
Bug #68027 (buffer overflow in mkgmtime() function)
--SKIPIF--
<?php
if (!extension_loaded("xmlrpc")) print "skip";
?>
--FILE--
<?php
$d = '6-01-01 20:00:00';
xmlrpc_set_type($d, 'datetime');
var_dump($d);
$datetime = "2001-0-08T21:46:40-0400";
$obj = xmlrpc_decode("<?xml version=\"1.0\"?><methodResponse><params><param><value><dateTime.iso8601>$datetime</dateTime.iso8601></value></param></params></methodResponse>");
print_r($obj);
$datetime = "34770-0-08T21:46:40-0400";
$obj = xmlrpc_decode("<?xml version=\"1.0\"?><methodResponse><params><param><value><dateTime.iso8601>$datetime</dateTime.iso8601></value></param></params></methodResponse>");
print_r($obj);
echo "Done\n";
?>
--EXPECTF--
object(stdClass)#1 (3) {
["scalar"]=>
string(16) "6-01-01 20:00:00"
["xmlrpc_type"]=>
string(8) "datetime"
["timestamp"]=>
int(%d)
}
stdClass Object
(
[scalar] => 2001-0-08T21:46:40-0400
[xmlrpc_type] => datetime
[timestamp] => %s
)
stdClass Object
(
[scalar] => 34770-0-08T21:46:40-0400
[xmlrpc_type] => datetime
[timestamp] => %d
)
Done