You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2011/09/26 22:05:10 UTC
svn commit: r1176018 - in /httpd/httpd/trunk: include/ap_mmn.h
include/util_varbuf.h server/util.c
Author: sf
Date: Mon Sep 26 20:05:09 2011
New Revision: 1176018
URL: http://svn.apache.org/viewvc?rev=1176018&view=rev
Log:
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.
Modified:
httpd/httpd/trunk/include/ap_mmn.h
httpd/httpd/trunk/include/util_varbuf.h
httpd/httpd/trunk/server/util.c
Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1176018&r1=1176017&r2=1176018&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Mon Sep 26 20:05:09 2011
@@ -354,6 +354,7 @@
* 20110724.7 (2.3.15-dev) add ap_random_insecure_bytes(), ap_random_pick()
* 20110724.8 (2.3.15-dev) add ap_abort_on_oom(), ap_malloc(), ap_calloc(),
* ap_realloc()
+ * 20110724.9 (2.3.15-dev) add ap_varbuf_pdup() and ap_varbuf_regsub()
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -361,7 +362,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20110724
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 8 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 9 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Modified: httpd/httpd/trunk/include/util_varbuf.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/util_varbuf.h?rev=1176018&r1=1176017&r2=1176018&view=diff
==============================================================================
--- httpd/httpd/trunk/include/util_varbuf.h (original)
+++ httpd/httpd/trunk/include/util_varbuf.h Mon Sep 26 20:05:09 2011
@@ -36,7 +36,7 @@ struct ap_varbuf_info;
/** A resizable buffer */
struct ap_varbuf {
- /** the actual buffer */
+ /** the actual buffer; will point to a const '\0' if avail == 0 */
char *buf;
/** allocated size of the buffer (minus one for the final \0);
@@ -100,6 +100,26 @@ AP_DECLARE(void) ap_varbuf_free(struct a
AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str,
int len);
+/** Duplicate an ap_varbuf's content into pool memory
+ * @param p the pool to allocate from
+ * @param vb the ap_varbuf to copy from
+ * @param prepend an optional buffer to prepend (may be NULL)
+ * @param prepend_len length of prepend
+ * @param append an optional buffer to append (may be NULL)
+ * @param append_len length of append
+ * @param new_len where to store the length of the resulting string
+ * (may be NULL)
+ * @return the new string
+ * @note ap_varbuf_pdup() uses vb->strlen to determine how much memory to
+ * copy. It works even if 0-bytes are embedded in vb->buf, prepend, or
+ * append
+ */
+AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *vb,
+ const char *prepend, apr_size_t prepend_len,
+ const char *append, apr_size_t append_len,
+ apr_size_t *new_len);
+
+
/** Concatenate a string to an ap_varbuf
* @param vb pointer to the ap_varbuf struct
* @param str the string to append
@@ -107,6 +127,22 @@ AP_DECLARE(void) ap_varbuf_strmemcat(str
*/
#define ap_varbuf_strcat(vb, str) ap_varbuf_strmemcat(vb, str, strlen(str))
+/** Perform string substitutions based on regexp match, using an ap_varbuf.
+ * This function behaves like ap_pregsub(), but appends to an ap_varbuf
+ * instead of allocating the result from a pool.
+ * @param input An arbitrary string containing $1 through $9. These are
+ * replaced with the corresponding matched sub-expressions
+ * @param source The string that was originally matched to the regex
+ * @param nmatch the nmatch returned from ap_pregex
+ * @param pmatch the pmatch array returned from ap_pregex
+ * @note Just like ap_pregsub(), this function does not copy the part of
+ * *source before the matching part (i.e. the first pmatch[0].rm_so
+ * characters).
+ */
+AP_DECLARE(void) ap_varbuf_regsub(struct ap_varbuf *vb, const char *input,
+ const char *source, size_t nmatch,
+ ap_regmatch_t pmatch[]);
+
/** Read a line from an ap_configfile_t into an ap_varbuf.
* @param vb pointer to the ap_varbuf struct
* @param cfg pointer to the ap_configfile_t
Modified: httpd/httpd/trunk/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?rev=1176018&r1=1176017&r2=1176018&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util.c (original)
+++ httpd/httpd/trunk/server/util.c Mon Sep 26 20:05:09 2011
@@ -361,15 +361,15 @@ AP_DECLARE(const char *) ap_stripprefix(
* 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
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
}
- 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
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
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 a
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 a
}
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 a
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 a
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 a
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