Coverage Report

Created: 2023-03-26 06:28

/src/httpd/srclib/apr/buckets/apr_buckets_pool.c
Line
Count
Source (jump to first uncovered line)
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include "apr_buckets.h"
18
#define APR_WANT_MEMFUNC
19
#include "apr_want.h"
20
21
static apr_status_t pool_bucket_cleanup(void *data)
22
0
{
23
0
    apr_bucket_pool *p = data;
24
25
    /*
26
     * If the pool gets cleaned up, we have to copy the data out
27
     * of the pool and onto the heap.  But the apr_buckets out there
28
     * that point to this pool bucket need to be notified such that
29
     * they can morph themselves into a regular heap bucket the next
30
     * time they try to read.  To avoid having to manipulate
31
     * reference counts and b->data pointers, the apr_bucket_pool
32
     * actually _contains_ an apr_bucket_heap as its first element,
33
     * so the two share their apr_bucket_refcount member, and you
34
     * can typecast a pool bucket struct to make it look like a
35
     * regular old heap bucket struct.
36
     */
37
0
    p->heap.base = apr_bucket_alloc(p->heap.alloc_len, p->list);
38
0
    memcpy(p->heap.base, p->base, p->heap.alloc_len);
39
0
    p->base = NULL;
40
0
    p->pool = NULL;
41
42
0
    return APR_SUCCESS;
43
0
}
44
45
static apr_status_t pool_bucket_read(apr_bucket *b, const char **str,
46
                                     apr_size_t *len, apr_read_type_e block)
47
0
{
48
0
    apr_bucket_pool *p = b->data;
49
0
    const char *base = p->base;
50
51
0
    if (p->pool == NULL) {
52
        /*
53
         * pool has been cleaned up... masquerade as a heap bucket from now
54
         * on. subsequent bucket operations will use the heap bucket code.
55
         */
56
0
        b->type = &apr_bucket_type_heap;
57
0
        base = p->heap.base;
58
0
    }
59
0
    *str = base + b->start;
60
0
    *len = b->length;
61
0
    return APR_SUCCESS;
62
0
}
63
64
static void pool_bucket_destroy(void *data)
65
0
{
66
0
    apr_bucket_pool *p = data;
67
68
    /* If the pool is cleaned up before the last reference goes
69
     * away, the data is really now on the heap; heap_destroy() takes
70
     * over.  free() in heap_destroy() thinks it's freeing
71
     * an apr_bucket_heap, when in reality it's freeing the whole
72
     * apr_bucket_pool for us.
73
     */
74
0
    if (p->pool) {
75
        /* the shared resource is still in the pool
76
         * because the pool has not been cleaned up yet
77
         */
78
0
        if (apr_bucket_shared_destroy(p)) {
79
0
            apr_pool_cleanup_kill(p->pool, p, pool_bucket_cleanup);
80
0
            apr_bucket_free(p);
81
0
        }
82
0
    }
83
0
    else {
84
        /* the shared resource is no longer in the pool, it's
85
         * on the heap, but this reference still thinks it's a pool
86
         * bucket.  we should just go ahead and pass control to
87
         * heap_destroy() for it since it doesn't know any better.
88
         */
89
0
        apr_bucket_type_heap.destroy(p);
90
0
    }
91
0
}
92
93
APR_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b,
94
                      const char *buf, apr_size_t length, apr_pool_t *pool)
95
0
{
96
0
    apr_bucket_pool *p;
97
98
0
    p = apr_bucket_alloc(sizeof(*p), b->list);
99
100
    /* XXX: we lose the const qualifier here which indicates
101
     * there's something screwy with the API...
102
     */
103
    /* XXX: why is this?  buf is const, p->base is const... what's
104
     * the problem?  --jcw */
105
0
    p->base = (char *) buf;
106
0
    p->pool = pool;
107
0
    p->list = b->list;
108
109
0
    b = apr_bucket_shared_make(b, p, 0, length);
110
0
    b->type = &apr_bucket_type_pool;
111
112
    /* pre-initialize heap bucket member */
113
0
    p->heap.alloc_len = length;
114
0
    p->heap.base      = NULL;
115
0
    p->heap.free_func = apr_bucket_free;
116
117
0
    apr_pool_cleanup_register(p->pool, p, pool_bucket_cleanup,
118
0
                              apr_pool_cleanup_null);
119
0
    return b;
120
0
}
121
122
APR_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf,
123
                                                 apr_size_t length,
124
                                                 apr_pool_t *pool,
125
                                                 apr_bucket_alloc_t *list)
126
0
{
127
0
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
128
129
0
    APR_BUCKET_INIT(b);
130
0
    b->free = apr_bucket_free;
131
0
    b->list = list;
132
0
    return apr_bucket_pool_make(b, buf, length, pool);
133
0
}
134
135
APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = {
136
    "POOL", 5, APR_BUCKET_DATA,
137
    pool_bucket_destroy,
138
    pool_bucket_read,
139
    apr_bucket_setaside_noop, /* don't need to setaside thanks to the cleanup*/
140
    apr_bucket_shared_split,
141
    apr_bucket_shared_copy
142
};