Index: modules/http/mod_mime.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/http/mod_mime.c,v
retrieving revision 1.54
diff -u -r1.54 mod_mime.c
--- modules/http/mod_mime.c	2001/08/16 21:23:29	1.54
+++ modules/http/mod_mime.c	2001/08/16 21:45:23
@@ -105,6 +105,7 @@
     char *language_type;              /* Added with AddLanguage... */
     char *handler;                    /* Added with AddHandler... */
     char *charset_type;               /* Added with AddCharset... */
+    apr_pool_t *pool;        /* To dup appropriately in the merge */
 } extension_info;
 
 typedef struct {
@@ -180,11 +181,18 @@
 
         base_info = (extension_info*)apr_hash_get(base, key, klen);
 
+        /* If we don't find the entry, simply add it (as is).
+         * If we find the entry, and this exinfo wasn't allocated from the 
+         * current pool, then we must copy before can merge the entry.
+         */
         if (base_info) {
-            extension_info *copyinfo = base_info;
-            base_info = (extension_info*)apr_palloc(p, sizeof(*base_info));
-            apr_hash_set(base, key, klen, base_info);
-            memcpy(base_info, copyinfo, sizeof(*base_info));
+            if (base_info->pool != p) {
+                extension_info *copyinfo = base_info;
+                base_info = (extension_info*)apr_palloc(p, sizeof(*base_info));
+                apr_hash_set(base, key, klen, base_info);
+                memcpy(base_info, copyinfo, sizeof(*base_info));
+                base_info->pool = p;
+            }
 
             if (overlay_info->forced_type) {
                 base_info->forced_type = overlay_info->forced_type;
@@ -220,12 +228,19 @@
             (extension_info*)apr_hash_get(mappings,
                                           suffix[i].name,
                                           APR_HASH_KEY_STRING);
+        /* If we find the entry, the given member isn't NULL,
+         * and this exinfo wasn't allocated from the current pool,
+         * then we must copy before we remove the given member.
+         */
         if (exinfo && *((void **)((char*)&exinfo + (apr_size_t)member))) {
-            extension_info *copyinfo = exinfo;
-            exinfo = (extension_info*)apr_palloc(p, sizeof(*exinfo));
-            apr_hash_set(mappings, suffix[i].name, 
-                         APR_HASH_KEY_STRING, exinfo);
-            memcpy(exinfo, copyinfo, sizeof(*exinfo));
+            if (exinfo->pool != p) {
+                extension_info *copyinfo = exinfo;
+                exinfo = (extension_info*)apr_palloc(p, sizeof(*exinfo));
+                apr_hash_set(mappings, suffix[i].name, 
+                             APR_HASH_KEY_STRING, exinfo);
+                memcpy(exinfo, copyinfo, sizeof(*exinfo));
+                exinfo->pool = p;
+            }
             *(void **)((char*)exinfo + (apr_size_t)member) = NULL;
         }
     }
@@ -237,10 +252,18 @@
     mime_dir_config *add = (mime_dir_config *) addv;
     mime_dir_config *new = apr_palloc(p, sizeof(mime_dir_config));
 
+    /* Given no mappings, we set up no mappings table. 
+     * If we are using the same pool as the base cfg, _or_
+     * we neither have anything to add or remove, we
+     * then we are safe retaining the existing hash.
+     * Otherwise we need a private copy of the hash table.
+     */
     if (base->extension_mappings && add->extension_mappings) {
-        new->extension_mappings = apr_hash_make(p);
-        overlay_extension_mappings(p, base->extension_mappings,
-                                   new->extension_mappings);
+        if (apr_hash_pool_get(base->extension_mappings) != p) {
+            new->extension_mappings = apr_hash_make(p);
+            overlay_extension_mappings(p, base->extension_mappings,
+                                       new->extension_mappings);
+        }
         overlay_extension_mappings(p, add->extension_mappings,
                                    new->extension_mappings);
     }
@@ -253,19 +276,26 @@
         }
         /* We may not be merging the tables, but if we potentially will change
          * an exinfo member, then we are about to trounce it anyways.
-         * We must have a copy for safety.
+         * We must have a copy if the pool changed, for safety.
          */
-        if (new->extension_mappings && (add->charsets_remove
-                                     || add->encodings_remove
-                                     || add->handlers_remove 
-                                     || add->languages_remove 
-                                     || add->types_remove)) {
+        if (new->extension_mappings
+                && (apr_hash_pool_get(new->extension_mappings) != p)
+                && (add->charsets_remove
+                 || add->encodings_remove
+                 || add->handlers_remove 
+                 || add->languages_remove 
+                 || add->types_remove)) {
             apr_hash_t *copyhash = new->extension_mappings;
             new->extension_mappings = apr_hash_make(p);
             overlay_extension_mappings(p, copyhash, new->extension_mappings);
         }
     }
 
+    /* Now we can add and remove hash table entries.  These functions
+     * are given a 'safe' hash they can modify, but they have to be
+     * careful to dup the actual hash entry if it isn't allocated from
+     * the given pool!
+     */
     if (new->extension_mappings) {
         if (add->charsets_remove)
             remove_items(p, add->charsets_remove, new->extension_mappings,
@@ -327,6 +357,7 @@
         key = apr_pstrdup(cmd->pool, key);
         apr_hash_set(m->extension_mappings, key,
                      APR_HASH_KEY_STRING, exinfo);
+        exinfo->pool = cmd->pool;
     }
     return exinfo;
 }
