]> granicus.if.org Git - php/commitdiff
Fixed zend_alter_ini_entry() memory_limit interruption vulnerability.
authorIlia Alshanetsky <iliaa@php.net>
Sun, 17 Jun 2007 14:31:12 +0000 (14:31 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Sun, 17 Jun 2007 14:31:12 +0000 (14:31 +0000)
NEWS
Zend/zend_ini.c

diff --git a/NEWS b/NEWS
index cda5ab36153b42f5e01bc6394d69306fcdc144fb..af49dfce799fbe423a9521af5351f51f32821bb4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ PHP                                                                        NEWS
 - Fixed size calculation in chunk_split(). (Stas)
 - Fixed integer overlow in str[c]spn(). (Stas)
 - Fixed money_format() not to accept multiple %i or %n tokens. (Stas, Ilia)
+- Fixed zend_alter_ini_entry() memory_limit interruption vulnerability.
+  (Ilia)
 
 - Fixed PECL bug #11216 (crash in ZipArchive::addEmptyDir when a directory 
   already exists). (Pierre)
index c559e661e4c8cf08af9d87258926c2efb02680ed..9b2a24c03cd660689938661d1122715bef4bbe11 100644 (file)
@@ -55,7 +55,9 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS
                                ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC);
                        } zend_end_try();
                }
-               efree(ini_entry->value);
+               if (ini_entry->value != ini_entry->orig_value) {
+                       efree(ini_entry->value);
+               }
                ini_entry->value = ini_entry->orig_value;
                ini_entry->value_length = ini_entry->orig_value_length;
                ini_entry->modified = 0;
@@ -234,34 +236,39 @@ ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value,
 {
        zend_ini_entry *ini_entry;
        char *duplicate;
+       zend_bool modified;
        TSRMLS_FETCH();
 
        if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) {
                return FAILURE;
        }
 
+       if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
+               ini_entry->modifiable = ZEND_INI_SYSTEM;
+       }
+
        if (!(ini_entry->modifiable & modify_type)) {
                return FAILURE;
        }
 
-       if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
-               ini_entry->modifiable = ZEND_INI_SYSTEM;
+       modified = ini_entry->modified;
+
+       if (!EG(modified_ini_directives)) {
+               ALLOC_HASHTABLE(EG(modified_ini_directives));
+               zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
+       }
+       if (!modified) {
+               ini_entry->orig_value = ini_entry->value;
+               ini_entry->orig_value_length = ini_entry->value_length;
+               ini_entry->modified = 1;
+               zend_hash_add(EG(modified_ini_directives), name, name_length, &ini_entry, sizeof(zend_ini_entry*), NULL);
        }
 
        duplicate = estrndup(new_value, new_value_length);
-       
+
        if (!ini_entry->on_modify
                || ini_entry->on_modify(ini_entry, duplicate, new_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC)==SUCCESS) {
-               if (!ini_entry->modified) {
-                       ini_entry->orig_value = ini_entry->value;
-                       ini_entry->orig_value_length = ini_entry->value_length;
-                       ini_entry->modified = 1;
-                       if (!EG(modified_ini_directives)) {
-                               ALLOC_HASHTABLE(EG(modified_ini_directives));
-                               zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
-                       }
-                       zend_hash_add(EG(modified_ini_directives), name, name_length, &ini_entry, sizeof(zend_ini_entry*), NULL);
-               } else { /* we already changed the value, free the changed value */
+               if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
                        efree(ini_entry->value);
                }
                ini_entry->value = duplicate;