diff options
author | Stefan Fritsch <sf@apache.org> | 2011-09-26 22:05:09 +0200 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2011-09-26 22:05:09 +0200 |
commit | e1fc6f9d0c3776f4b95261e4a75f71d0073fbb81 (patch) | |
tree | f383affdaeb83bae206ee1bc37ac6f5e6a4fb5d4 /server | |
parent | Adjust log message to reflect changed behaviour (diff) | |
download | apache2-e1fc6f9d0c3776f4b95261e4a75f71d0073fbb81.tar.xz apache2-e1fc6f9d0c3776f4b95261e4a75f71d0073fbb81.zip |
Some varbuf enhancements:
- Introduce new ap_varbuf_pdup() and ap_varbuf_regsub() functions.
- Fix some bugs in ap_varbuf_strmemcat().
- Make ap_varbuf.buf point to an empty string if no buffer has been allocated,
yet.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1176018 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r-- | server/util.c | 105 |
1 files changed, 86 insertions, 19 deletions
diff --git a/server/util.c b/server/util.c index a6c60a9f2a..e58ad76aeb 100644 --- a/server/util.c +++ b/server/util.c @@ -361,15 +361,15 @@ AP_DECLARE(const char *) ap_stripprefix(const char *bigstring, * input should be the string with the $-expressions, source should be the * string that was matched against. * - * It returns the substituted string, or NULL on error. + * It returns the substituted string, or NULL if a vbuf is used. * * Parts of this code are based on Henry Spencer's regsub(), from his * AT&T V8 regexp package. */ -AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, - const char *source, size_t nmatch, - ap_regmatch_t pmatch[]) +static char *regsub_core(apr_pool_t *p, struct ap_varbuf *vb, + const char *input, const char *source, + size_t nmatch, ap_regmatch_t pmatch[]) { const char *src = input; char *dest, *dst; @@ -379,8 +379,15 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, if (!source) return NULL; - if (!nmatch) - return apr_pstrdup(p, src); + if (!nmatch) { + if (!vb) { + return apr_pstrdup(p, src); + } + else { + ap_varbuf_strcat(vb, src); + return NULL; + } + } /* First pass, find the size */ @@ -403,7 +410,16 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, } - dest = dst = apr_pcalloc(p, len + 1); + if (!vb) { + dest = dst = apr_pcalloc(p, len + 1); + } + else { + if (vb->buf && vb->strlen == AP_VARBUF_UNKNOWN) + vb->strlen = strlen(vb->buf); + ap_varbuf_grow(vb, vb->strlen + len); + dest = dst = vb->buf + vb->strlen; + vb->strlen += len; + } /* Now actually fill in the string */ @@ -434,6 +450,13 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, return dest; } +AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, + const char *source, size_t nmatch, + ap_regmatch_t pmatch[]) +{ + return regsub_core(p, NULL, input, source, nmatch, pmatch); +} + /* * Parse .. so we don't compromise security */ @@ -2462,10 +2485,13 @@ static apr_status_t varbuf_cleanup(void *info_) return APR_SUCCESS; } +const char nul = '\0'; +static char * const varbuf_empty = (char *)&nul; + AP_DECLARE(void) ap_varbuf_init(apr_pool_t *p, struct ap_varbuf *vb, apr_size_t init_size) { - vb->buf = NULL; + vb->buf = varbuf_empty; vb->avail = 0; vb->strlen = AP_VARBUF_UNKNOWN; vb->pool = p; @@ -2499,8 +2525,9 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len) if (new_len <= VARBUF_SMALL_SIZE) { new_len = APR_ALIGN_DEFAULT(new_len); new = apr_palloc(vb->pool, new_len); - if (vb->buf && vb->strlen > 0) { - AP_DEBUG_ASSERT(vb->avail > 0); + if (vb->avail && vb->strlen != 0) { + AP_DEBUG_ASSERT(vb->buf != NULL); + AP_DEBUG_ASSERT(vb->buf != varbuf_empty); if (new == vb->buf + vb->avail + 1) { /* We are lucky: the new memory lies directly after our old * buffer, we can now use both. @@ -2510,7 +2537,7 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len) } else { /* copy up to vb->strlen + 1 bytes */ - memcpy(new, vb->buf, vb->strlen > vb->avail ? + memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ? vb->avail + 1 : vb->strlen + 1); } } @@ -2542,9 +2569,9 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len) AP_DEBUG_ASSERT(new_node->endp - new_node->first_avail >= new_len); new_len = new_node->endp - new_node->first_avail; - if (vb->buf && vb->strlen > 0) - memcpy(new, vb->buf, vb->strlen > vb->avail ? - vb->avail + 1: vb->strlen + 1); + if (vb->avail && vb->strlen != 0) + memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ? + vb->avail + 1 : vb->strlen + 1); else *new = '\0'; if (vb->info) @@ -2559,16 +2586,17 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len) AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str, int len) { - AP_DEBUG_ASSERT(len == strlen(str)); + if (len == 0) + return; if (!vb->avail) { ap_varbuf_grow(vb, len); - memcpy(vb->buf, str, len + 1); + memcpy(vb->buf, str, len); + vb->buf[len] = '\0'; + vb->strlen = len; return; } - if (vb->strlen > vb->avail) { - AP_DEBUG_ASSERT(vb->strlen == AP_VARBUF_UNKNOWN); + if (vb->strlen == AP_VARBUF_UNKNOWN) vb->strlen = strlen(vb->buf); - } ap_varbuf_grow(vb, vb->strlen + len); memcpy(vb->buf + vb->strlen, str, len); vb->strlen += len; @@ -2584,6 +2612,45 @@ AP_DECLARE(void) ap_varbuf_free(struct ap_varbuf *vb) vb->buf = NULL; } +AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *buf, + const char *prepend, apr_size_t prepend_len, + const char *append, apr_size_t append_len, + apr_size_t *new_len) +{ + apr_size_t i = 0; + struct iovec vec[3]; + + if (prepend) { + vec[i].iov_base = (void *)prepend; + vec[i].iov_len = prepend_len; + i++; + } + if (buf->avail && buf->strlen) { + vec[i].iov_base = (void *)buf->buf; + vec[i].iov_len = (buf->strlen == AP_VARBUF_UNKNOWN) ? buf->avail + : buf->strlen; + i++; + } + if (append) { + vec[i].iov_base = (void *)append; + vec[i].iov_len = append_len; + i++; + } + if (i) + return apr_pstrcatv(p, vec, i, new_len); + + if (new_len) + *new_len = 0; + return ""; +} + +AP_DECLARE(void) ap_varbuf_regsub(struct ap_varbuf *vb, const char *input, + const char *source, size_t nmatch, + ap_regmatch_t pmatch[]) +{ + regsub_core(NULL, vb, input, source, nmatch, pmatch); +} + #define OOM_MESSAGE "[crit] Memory allocation failed, " \ "aborting process." APR_EOL_STR |