Skip to content

Commit

Permalink
Also reject negative format values in APCuIterator
Browse files Browse the repository at this point in the history
This would affect applications that accidentally or deliberately pass in
negative values for $format (e.g. PHP_INT_MIN on 64-bit builds)

The apc_error macro surprisingly calls php_verror, which is a fatal error.
Switch this to zend_throw_error instead - this still supports PHP 8.0 so
ValueError is too new.
  • Loading branch information
TysonAndre committed Nov 13, 2022
1 parent eb6b9bd commit 2e79183
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 9 deletions.
11 changes: 6 additions & 5 deletions apc_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,15 +316,15 @@ static void apc_iterator_totals(apc_iterator_t *iterator) {
}
/* }}} */

void apc_iterator_obj_init(apc_iterator_t *iterator, zval *search, zend_long format, size_t chunk_size, zend_long list)
void apc_iterator_obj_init(apc_iterator_t *iterator, zval *search, zend_ulong format, size_t chunk_size, zend_long list)
{
if (!APCG(enabled)) {
zend_throw_error(NULL, "APC must be enabled to use APCUIterator");
return;
}

if (format > APC_ITER_ALL) {
apc_error("APCUIterator format is invalid");
zend_throw_error(NULL, "APCUIterator format is invalid");
return;
}

Expand Down Expand Up @@ -354,9 +354,10 @@ void apc_iterator_obj_init(apc_iterator_t *iterator, zval *search, zend_long for
iterator->pce = pcre_get_compiled_regex_cache(iterator->regex);

if (!iterator->pce) {
apc_error("Could not compile regular expression: %s", Z_STRVAL_P(search));
zend_throw_error(NULL, "Could not compile regular expression: %s", Z_STRVAL_P(search));
zend_string_release(iterator->regex);
iterator->regex = NULL;
return;
}

#if PHP_VERSION_ID >= 70300
Expand Down Expand Up @@ -385,7 +386,7 @@ PHP_METHOD(APCUIterator, __construct) {
ZEND_PARSE_PARAMETERS_END();

if (chunk_size < 0) {
apc_error("APCUIterator chunk size must be 0 or greater");
zend_throw_error(NULL, "APCUIterator chunk size must be 0 or greater");
return;
}

Expand Down Expand Up @@ -580,7 +581,7 @@ int apc_iterator_delete(zval *zobj) {
apc_iterator_item_t *item;

if (!ce || !instanceof_function(ce, apc_iterator_ce)) {
apc_error("apc_delete object argument must be instance of APCUIterator.");
apc_warning("apcu_delete object argument must be an instance of APCUIterator.");
return 0;
}
iterator = apc_iterator_fetch(zobj);
Expand Down
4 changes: 2 additions & 2 deletions apc_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
/* {{{ apc_iterator_t */
typedef struct _apc_iterator_t {
short int initialized; /* sanity check in case __construct failed */
zend_long format; /* format bitmask of the return values ie: key, value, info */
zend_ulong format; /* format bitmask of the return values ie: key, value, info */
size_t (*fetch)(struct _apc_iterator_t *iterator);
/* fetch callback to fetch items from cache slots or lists */
size_t slot_idx; /* index to the slot array or linked list */
Expand Down Expand Up @@ -84,7 +84,7 @@ typedef struct _apc_iterator_item_t {
PHP_APCU_API void apc_iterator_obj_init(
apc_iterator_t *iterator,
zval *search,
zend_long format,
zend_ulong format,
size_t chunk_size,
zend_long list);
PHP_APCU_API zend_class_entry* apc_iterator_get_ce(void);
Expand Down
1 change: 1 addition & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
<file name="iterator_009.phpt" role="test" />
<file name="iterator_010.phpt" role="test" />
<file name="iterator_011.phpt" role="test" />
<file name="iterator_012.phpt" role="test" />
<file name="not_enough_shm.phpt" role="test" />
<file name="server_test.inc" role="test" />
<file name="skipif.inc" role="test" />
Expand Down
4 changes: 2 additions & 2 deletions php_apc.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ PHP_FUNCTION(apcu_delete) {
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), hentry) {
ZVAL_DEREF(hentry);
if (Z_TYPE_P(hentry) != IS_STRING) {
apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance");
apc_warning("apcu_delete() expects a string, array of strings, or APCUIterator instance");
add_next_index_zval(return_value, hentry);
Z_TRY_ADDREF_P(hentry);
} else if (apc_cache_delete(apc_user_cache, Z_STR_P(hentry)) != 1) {
Expand All @@ -759,7 +759,7 @@ PHP_FUNCTION(apcu_delete) {
} else if (Z_TYPE_P(keys) == IS_OBJECT) {
RETURN_BOOL(apc_iterator_delete(keys) != 0);
} else {
apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance");
apc_warning("apcu_delete() expects a string, array of strings, or APCUIterator instance");
RETURN_FALSE;
}
}
Expand Down
40 changes: 40 additions & 0 deletions tests/iterator_012.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
APC: APCIterator throws for invalid flags
--SKIPIF--
<?php
require_once(dirname(__FILE__) . '/skipif.inc');
if (PHP_INT_SIZE == 4) echo "skip 64-bit only\n";
?>
--INI--
apc.enabled=1
apc.enable_cli=1
--FILE--
<?php
foreach ([[null, -1], [null, PHP_INT_MAX], ['/invalidRegex'], [null, 0, -1]] as $args) {
try {
var_dump(new APCuIterator(...$args));
} catch (Throwable $e) {
printf("Caught %s: %s\n", get_class($e), $e->getMessage());
}
}
foreach ([[[]], 4.2, new stdClass()] as $delete) {
try {
apcu_delete($delete);
} catch (Throwable $e) {
printf("Caught %s: %s\n", get_class($e), $e->getMessage());
}
}
?>
--EXPECTF--
Caught Error: APCUIterator format is invalid
Caught Error: APCUIterator format is invalid

Warning: APCUIterator::__construct(): No ending delimiter '/' found in %s on line 4
Caught Error: Could not compile regular expression: /invalidRegex
Caught Error: APCUIterator chunk size must be 0 or greater

Warning: apcu_delete(): apcu_delete() expects a string, array of strings, or APCUIterator instance in %s on line 11

Warning: apcu_delete(): apcu_delete() expects a string, array of strings, or APCUIterator instance in %s on line 11

Warning: apcu_delete(): apcu_delete object argument must be an instance of APCUIterator. in %s on line 11

0 comments on commit 2e79183

Please sign in to comment.