| 2969 | } |
| 2970 | |
| 2971 | AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len) |
| 2972 | { |
| 2973 | apr_memnode_t *new_node = NULL; |
| 2974 | apr_allocator_t *allocator; |
| 2975 | struct ap_varbuf_info *new_info; |
| 2976 | char *new; |
| 2977 | |
| 2978 | AP_DEBUG_ASSERT(vb->strlen == AP_VARBUF_UNKNOWN || vb->avail >= vb->strlen); |
| 2979 | |
| 2980 | if (new_len <= vb->avail) |
| 2981 | return; |
| 2982 | |
| 2983 | if (new_len < 2 * vb->avail && vb->avail < VARBUF_MAX_SIZE/2) { |
| 2984 | /* at least double the size, to avoid repeated reallocations */ |
| 2985 | new_len = 2 * vb->avail; |
| 2986 | } |
| 2987 | else if (new_len > VARBUF_MAX_SIZE) { |
| 2988 | apr_abortfunc_t abort_fn = apr_pool_abort_get(vb->pool); |
| 2989 | ap_assert(abort_fn != NULL); |
| 2990 | abort_fn(APR_ENOMEM); |
| 2991 | return; |
| 2992 | } |
| 2993 | |
| 2994 | new_len++; /* add space for trailing \0 */ |
| 2995 | if (new_len <= VARBUF_SMALL_SIZE) { |
| 2996 | new_len = APR_ALIGN_DEFAULT(new_len); |
| 2997 | new = apr_palloc(vb->pool, new_len); |
| 2998 | if (vb->avail && vb->strlen != 0) { |
| 2999 | AP_DEBUG_ASSERT(vb->buf != NULL); |
| 3000 | AP_DEBUG_ASSERT(vb->buf != varbuf_empty); |
| 3001 | if (new == vb->buf + vb->avail + 1) { |
| 3002 | /* We are lucky: the new memory lies directly after our old |
| 3003 | * buffer, we can now use both. |
| 3004 | */ |
| 3005 | vb->avail += new_len; |
| 3006 | return; |
| 3007 | } |
| 3008 | else { |
| 3009 | /* copy up to vb->strlen + 1 bytes */ |
| 3010 | memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ? |
| 3011 | vb->avail + 1 : vb->strlen + 1); |
| 3012 | } |
| 3013 | } |
| 3014 | else { |
| 3015 | *new = '\0'; |
| 3016 | } |
| 3017 | vb->avail = new_len - 1; |
| 3018 | vb->buf = new; |
| 3019 | return; |
| 3020 | } |
| 3021 | |
| 3022 | /* The required block is rather larger. Use allocator directly so that |
| 3023 | * the memory can be freed independently from the pool. */ |
| 3024 | allocator = apr_pool_allocator_get(vb->pool); |
| 3025 | /* Happens if APR was compiled with APR_POOL_DEBUG */ |
| 3026 | if (allocator == NULL) { |
| 3027 | apr_allocator_create(&allocator); |
| 3028 | ap_assert(allocator != NULL); |
no outgoing calls
no test coverage detected