diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 98e90c9ab93..af540a520cc 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1635,7 +1635,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char const char zip_magic[] = "PK\x03\x04"; const char gz_magic[] = "\x1f\x8b\x08"; const char bz_magic[] = "BZh"; - char *pos, test = '\0'; + char *pos; + int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion const int window_size = 1024; char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */ const zend_long readsize = sizeof(buffer) - sizeof(token); @@ -1663,8 +1664,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") } - if (!test) { - test = '\1'; + if (recursion_count) { pos = buffer+tokenlen; if (!memcmp(pos, gz_magic, 3)) { char err = 0; @@ -1724,7 +1724,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_GZ; /* now, start over */ - test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\""); + break; + } continue; } else if (!memcmp(pos, bz_magic, 3)) { php_stream_filter *filter; @@ -1762,7 +1765,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_BZ2; /* now, start over */ - test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\""); + break; + } continue; } diff --git a/ext/phar/tests/bug81726.gz b/ext/phar/tests/bug81726.gz new file mode 100644 index 00000000000..67b41ba3b65 Binary files /dev/null and b/ext/phar/tests/bug81726.gz differ diff --git a/ext/phar/tests/bug81726.phpt b/ext/phar/tests/bug81726.phpt new file mode 100644 index 00000000000..11a148c28ea --- /dev/null +++ b/ext/phar/tests/bug81726.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #81726 (phar wrapper: DOS when using quine gzip file) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: fopen(phar://%s): failed to open stream: unable to decompress gzipped phar archive "%s" in %s on line %d +bool(false) diff --git a/ext/standard/tests/bug81727.phpt b/ext/standard/tests/bug81727.phpt new file mode 100644 index 00000000000..71a9cb46c83 --- /dev/null +++ b/ext/standard/tests/bug81727.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #81727: $_COOKIE name starting with ..Host/..Secure should be discarded +--COOKIE-- +..Host-test=ignore; __Host-test=correct; . Secure-test=ignore; . Elephpant=Awesome; +--FILE-- + +--EXPECT-- +array(2) { + ["__Host-test"]=> + string(7) "correct" + ["__Elephpant"]=> + string(7) "Awesome" +} diff --git a/main/php_variables.c b/main/php_variables.c index 6a8ff5e1f09..27a9ad089e7 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -104,6 +104,20 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac } var_len = p - var; + /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */ + if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + + /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ + if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + if (var_len==0) { /* empty variable name, or variable name with a space in it */ zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap);