Issue Details (XML | Word | Printable)

Key: MODPYTHON-75
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Jim Gallacher
Reporter: Boyan Boyadjiev
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
mod_python

Crash and memory leak in python_merge_config due to use of apr_table_overlap

Created: 25/Aug/05 11:19 PM   Updated: 05/Mar/06 02:21 PM
Return to search
Component/s: core
Affects Version/s: 3.1.3, 3.1.4
Fix Version/s: 3.2.7

Time Tracking:
Not Specified

Environment: all

Resolution Date: 17/Sep/05 12:06 AM


 Description  « Hide
Couse:
Usage of apr_table_overlap() function in the python_merge_config() and the way of handling the pools for resource allocation there. In general using this function in python_merge_config() mismatches the pool designated for global configuration items and the one that has to be used for request local data. By using a global pool for local data two request may collide when accessing this one which leads to the crash.

The solution which works fine for us is to implement and use a custom_table_overlap function, which does apr_table_overlay and then apr_table_compress (similar aproach as in mod_perl):

/*
code begin
*/
/**
 ** modpython_table_overlap
 **
 * Replaces the apr_table_overlap() function using a specific pool
 * for the resulting table.
 */

static apr_table_t *modpython_table_overlap(apr_pool_t *p,
                                            apr_table_t *current_table,
                                            apr_table_t *new_table)
{
    apr_table_t *merge = apr_table_overlay(p, current_table, new_table);
    apr_table_compress(merge, APR_OVERLAP_TABLES_SET);
    return merge;
}

/**
 ** python_merge_dir_config
 **
 */

static void *python_merge_config(apr_pool_t *p, void *current_conf,
                                 void *new_conf)
{

    py_config *merged_conf =
        (py_config *) apr_pcalloc(p, sizeof(py_config));
    py_config *cc = (py_config *) current_conf;
    py_config *nc = (py_config *) new_conf;

    apr_hash_index_t *hi;
    char *key;
    apr_ssize_t klen;
    hl_entry *hle;

    /* we basically allow the local configuration to override global,
     * by first copying current values and then new values on top
     */

    /** create **/
    merged_conf->hlists = apr_hash_make(p);
    merged_conf->in_filters = apr_hash_make(p);
    merged_conf->out_filters = apr_hash_make(p);

    /** merge directives and options **/
    merged_conf->directives = modpython_table_overlap(p, cc->directives,
                                                         nc->directives);
    merged_conf->options = modpython_table_overlap(p, cc->options,
                                                      nc->options);

    /** copy current **/
    merged_conf->authoritative = cc->authoritative;
    merged_conf->config_dir = apr_pstrdup(p, cc->config_dir);

    for (hi = apr_hash_first(p, cc->hlists); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void **)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->hlists, key, klen, (void *)hle);
    }

    for (hi = apr_hash_first(p, cc->in_filters); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void **)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->in_filters, key, klen, (void *)hle);
    }

    for (hi = apr_hash_first(p, cc->out_filters); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void **)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->out_filters, key, klen, (void *)hle);
    }

    /** copy new **/

    if (nc->authoritative != merged_conf->authoritative)
        merged_conf->authoritative = nc->authoritative;
    if (nc->config_dir)
        merged_conf->config_dir = apr_pstrdup(p, nc->config_dir);

    for (hi = apr_hash_first(p, nc->hlists); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void**)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->hlists, key, klen, (void *)hle);
    }

    for (hi = apr_hash_first(p, nc->in_filters); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void**)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->in_filters, key, klen, (void *)hle);
    }

    for (hi = apr_hash_first(p, nc->out_filters); hi; hi=apr_hash_next(hi)) {
        apr_hash_this(hi, (const void**)&key, &klen, (void **)&hle);
        apr_hash_set(merged_conf->out_filters, key, klen, (void *)hle);
    }

    return (void *) merged_conf;
}

/*
code end
*/

 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Repository Revision Date User Message
ASF #263916 Sun Aug 28 20:39:51 UTC 2005 jgallacher Fixed crash and memory leak in python_merge_config function in mod_python.c
described in MODPYTHON-75. Boyan Boyadjiev provided the code which corrected
the problem. This also fixes the memory leak resulting in the use of any
PythonOption directive as described in MODPYTHON-60.
Files Changed
MODIFY /httpd/mod_python/trunk/src/mod_python.c
MODIFY /httpd/mod_python/trunk/src/include/mpversion.h