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