From a5c1e289d380aeb5440be033bae858db2a84c890 Mon Sep 17 00:00:00 2001 From: aszlig Date: Sat, 14 Dec 2019 00:54:19 +0100 Subject: [PATCH] php: Fix memory corruption for uwsgi_cache_* Ah the joys of variadic arguments in C... So, when using zend_parse_parameters(), PHP internally loops through the type specifiers and accordingly uses va_arg() to get the corresponding argument. Since the arguments are expected to be pointers to the corresponding values, the size of them *does* matter, because PHP simply writes to the corresponding address with a size of size_t. If we for example pass a pointer to a 32bit integer and PHP writes 64 bits, we have an overflow of 4 bytes. From README.PARAMETER_PARSING_API in the PHP source tree: > Please note that since version 7 PHP uses zend_long as integer type > and zend_string with size_t as length, so make sure you pass > zend_longs to "l" and size_t to strings length (i.e. for "s" you need > to pass char * and size_t), not the other way round! > > Both mistakes might cause memory corruptions and segfaults: > 1) > char *str; > long str_len; /* XXX THIS IS WRONG!! Use size_t instead. */ > zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) > > 2) > int num; /* XXX THIS IS WRONG!! Use zend_long instead. */ > zend_parse_parameters(ZEND_NUM_ARGS(), "l", &num) To fix this, I changed the types accordingly to use size_t and zend_long if the PHP major version is >= 7. Signed-off-by: aszlig --- plugins/php/php_plugin.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/php/php_plugin.c b/plugins/php/php_plugin.c index 50d3b8046..339c9fe50 100644 --- a/plugins/php/php_plugin.c +++ b/plugins/php/php_plugin.c @@ -275,9 +275,9 @@ PHP_FUNCTION(uwsgi_masterpid) { PHP_FUNCTION(uwsgi_cache_exists) { char *key = NULL; - int keylen = 0; + php_strlen_size keylen = 0; char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) { RETURN_NULL(); @@ -293,7 +293,7 @@ PHP_FUNCTION(uwsgi_cache_exists) { PHP_FUNCTION(uwsgi_cache_clear) { char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &cache, &cachelen) == FAILURE) { RETURN_NULL(); @@ -308,11 +308,11 @@ PHP_FUNCTION(uwsgi_cache_clear) { PHP_FUNCTION(uwsgi_cache_del) { - + char *key = NULL; - int keylen = 0; + php_strlen_size keylen = 0; char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) { RETURN_NULL(); @@ -328,9 +328,9 @@ PHP_FUNCTION(uwsgi_cache_del) { PHP_FUNCTION(uwsgi_cache_get) { char *key = NULL; - int keylen = 0; + php_strlen_size keylen = 0; char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; uint64_t valsize; if (!uwsgi.caches) @@ -351,12 +351,12 @@ PHP_FUNCTION(uwsgi_cache_get) { PHP_FUNCTION(uwsgi_cache_set) { char *key = NULL; - int keylen; + php_strlen_size keylen = 0; char *value = NULL; - int vallen; - uint64_t expires = 0; + php_strlen_size vallen = 0; + php_long_size expires = 0; char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; if (!uwsgi.caches) RETURN_NULL(); @@ -374,12 +374,12 @@ PHP_FUNCTION(uwsgi_cache_set) { PHP_FUNCTION(uwsgi_cache_update) { char *key = NULL; - int keylen; + php_strlen_size keylen = 0; char *value = NULL; - int vallen; - uint64_t expires = 0; + php_strlen_size vallen = 0; + php_long_size expires = 0; char *cache = NULL; - int cachelen = 0; + php_strlen_size cachelen = 0; if (!uwsgi.caches) RETURN_NULL();