]> granicus.if.org Git - apache/commitdiff
Merge r1359884:
authorStefan Fritsch <sf@apache.org>
Sun, 9 Dec 2012 13:15:02 +0000 (13:15 +0000)
committerStefan Fritsch <sf@apache.org>
Sun, 9 Dec 2012 13:15:02 +0000 (13:15 +0000)
    make varbuf functions treat AP_VARBUF_UNKNOWN consistently, improve docs

    ap_varbuf_pdup(): copying the whole buffer in case strlen ==
    AP_VARBUF_UNKNOWN does not make sense as the caller can not set
    the exact buffer size, only a minimum. No API change as previously
    the behavior with AP_VARBUF_UNKNOWN was undocumented.

    regsub_core(): Checking for vb->buf is useless, it cannot be NULL
    unless ap_varbuf_init has not been called.

    ap_varbuf_cfg_getline(): Initially, allocate enough memory to hold
    an empty line. If strlen == AP_VARBUF_UNKNOWN, use strlen(buf) instead
    of undefined behavior.

Reviewed by: jim, sf, minfrin

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1418935 13f79535-47bb-0310-9956-ffa450edef68

STATUS
include/util_varbuf.h
server/util.c

diff --git a/STATUS b/STATUS
index 569b96059b022f892797206691db57d2cc969489..ed5708728fde8bf5b90d70613329c927c2261fac 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -91,11 +91,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-   * util: make varbuf functions treat AP_VARBUF_UNKNOWN consistently
-     trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1359884
-     2.4.x patch: trunk patch works
-     +1: jim, sf, minfrin
-
     * mod_headers: Allow for exposure of loadavg and server load via mod_headers
       trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1389565
                    http://svn.apache.org/viewvc?view=revision&revision=1389566
index 1ae99f911e2b1fba440bb072b2930592249f4f58..cf4bc7ffe3ef4c4a33f768e3c71530547d8db38c 100644 (file)
 /**
  * @file util_varbuf.h
  * @brief Apache resizable variable length buffer library
+ *
+ * This set of functions provides resizable buffers. While the primary
+ * usage is with NUL-terminated strings, most functions also work with
+ * arbitrary binary data.
+ *
+ * @defgroup APACHE_CORE_VARBUF
+ * @ingroup APACHE_CORE
+ * @{
  */
 
 #ifndef AP_VARBUF_H
@@ -36,7 +44,8 @@ struct ap_varbuf_info;
 
 /** A resizable buffer */
 struct ap_varbuf {
-    /** the actual buffer; will point to a const '\0' if avail == 0 */
+    /** the actual buffer; will point to a const '\0' if avail == 0 and
+     *  to memory of the same lifetime as the pool otherwise */
     char *buf;
 
     /** allocated size of the buffer (minus one for the final \0);
@@ -49,7 +58,7 @@ struct ap_varbuf {
     apr_size_t strlen;
 
     /** the pool for memory allocations and for registering the cleanup;
-     *  the buffer memory will be released when this pool is destroyed */
+     *  the buffer memory will be released when this pool is cleared */
     apr_pool_t *pool;
 
     /** opaque info for memory allocation */
@@ -58,7 +67,8 @@ struct ap_varbuf {
 
 /** initialize a resizable buffer. It is safe to re-initialize a prevously
  *  used ap_varbuf. The old buffer will be released when the corresponding
- *  pool is destroyed.
+ *  pool is cleared. The buffer remains usable until the pool is cleared,
+ *  even if the ap_varbuf was located on the stack and has gone out of scope.
  * @param pool the pool to allocate small buffers from and to register the
  *        cleanup with
  * @param vb pointer to the ap_varbuf struct
@@ -68,8 +78,8 @@ AP_DECLARE(void) ap_varbuf_init(apr_pool_t *pool, struct ap_varbuf *vb,
                                 apr_size_t init_size);
 
 /** grow a resizable buffer. If the vb->buf cannot be grown in place, it will
- *  be reallocated and up to vb->strlen + 1 bytes of memory will be copied to
- *  the new location. If vb->strlen == AP_VARBUF_UNKNOWN, the whole buffer
+ *  be reallocated and the first vb->strlen + 1 bytes of memory will be copied
+ *  to the new location. If vb->strlen == AP_VARBUF_UNKNOWN, the whole buffer
  *  is copied.
  * @param vb pointer to the ap_varbuf struct
  * @param new_size the minimum new size of the buffer
@@ -83,19 +93,22 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_size);
 
 /** Release memory from a ap_varbuf immediately, if possible.
  *  This allows to free large buffers before the corresponding pool is
- *  destroyed. Only larger allocations using mem nodes will be freed.
+ *  cleared. Only larger allocations using mem nodes will be freed.
  * @param vb pointer to the ap_varbuf struct
  * @note After ap_varbuf_free(), vb must not be used unless ap_varbuf_init()
  *       is called again.
  */
 AP_DECLARE(void) ap_varbuf_free(struct ap_varbuf *vb);
 
-/** Concatenate a string to an ap_varbuf
+/** Concatenate a string to an ap_varbuf. vb->strlen determines where
+ * the string is appended in the buffer. If vb->strlen == AP_VARBUF_UNKNOWN,
+ * the string will be appended at the first NUL byte in the buffer.
+ * If len == 0, ap_varbuf_strmemcat() does nothing.
  * @param vb pointer to the ap_varbuf struct
  * @param str the string to append; must be at least len bytes long
  * @param len the number of characters of *str to concatenate to the buf
  * @note vb->strlen will be set to the length of the new string
- * @note vb->buf will be null-terminated
+ * @note if len != 0, vb->buf will always be NUL-terminated
  */
 AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str,
                                      int len);
@@ -112,7 +125,9 @@ AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str,
  * @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
+ *       append.
+ * @note If vb->strlen equals AP_VARBUF_UNKNOWN, it will be set to
+ *       strlen(vb->buf).
  */
 AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *vb,
                                   const char *prepend, apr_size_t prepend_len,
@@ -141,6 +156,8 @@ AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *vb,
  * @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).
+ * @note If vb->strlen equals AP_VARBUF_UNKNOWN, it will be set to
+ *       strlen(vb->buf) first.
  */
 AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb,
                                           const char *input,
@@ -149,12 +166,14 @@ AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb,
                                           ap_regmatch_t pmatch[],
                                           apr_size_t maxlen);
 
-/** Read a line from an ap_configfile_t into an ap_varbuf.
+/** Read a line from an ap_configfile_t and append it to an ap_varbuf.
  * @param vb pointer to the ap_varbuf struct
  * @param cfg pointer to the ap_configfile_t
  * @param max_len maximum line length, including leading/trailing whitespace
  * @return see ap_cfg_getline()
  * @note vb->strlen will be set to the length of the line
+ * @note If vb->strlen equals AP_VARBUF_UNKNOWN, it will be set to
+ *       strlen(vb->buf) first.
  */
 AP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
                                                ap_configfile_t *cfp,
@@ -165,3 +184,4 @@ AP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
 #endif
 
 #endif  /* !AP_VARBUF_H */
+/** @} */
index 63d5192a1cdde48bd6c0ab80b663e20e9a5e2f92..36c278409142e1fee5963315f7d0ad4068a4a082 100644 (file)
@@ -432,7 +432,7 @@ static apr_status_t regsub_core(apr_pool_t *p, char **result,
         *result = dst = apr_palloc(p, len + 1);
     }
     else {
-        if (vb->buf && vb->strlen == AP_VARBUF_UNKNOWN)
+        if (vb->strlen == AP_VARBUF_UNKNOWN)
             vb->strlen = strlen(vb->buf);
         ap_varbuf_grow(vb, vb->strlen + len);
         dst = vb->buf + vb->strlen;
@@ -1100,11 +1100,22 @@ AP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
                                                apr_size_t max_len)
 {
     apr_status_t rc;
+    apr_size_t new_len;
     vb->strlen = 0;
     *vb->buf = '\0';
 
+    if (vb->strlen == AP_VARBUF_UNKNOWN)
+        vb->strlen = strlen(vb->buf);
+    if (vb->avail - vb->strlen < 3) {
+        new_len = vb->avail * 2;
+        if (new_len > max_len)
+            new_len = max_len;
+        else if (new_len < 3)
+            new_len = 3;
+        ap_varbuf_grow(vb, new_len);
+    }
+
     for (;;) {
-        apr_size_t new_len;
         rc = ap_cfg_getline_core(vb->buf + vb->strlen, vb->avail - vb->strlen, cfp);
         if (rc == APR_ENOSPC || rc == APR_SUCCESS)
             vb->strlen += strlen(vb->buf + vb->strlen);
@@ -2590,6 +2601,8 @@ AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len)
     struct ap_varbuf_info *new_info;
     char *new;
 
+    AP_DEBUG_ASSERT(vb->strlen == AP_VARBUF_UNKNOWN || vb->avail >= vb->strlen);
+
     if (new_len <= vb->avail)
         return;
 
@@ -2709,9 +2722,10 @@ AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *buf,
         i++;
     }
     if (buf->avail && buf->strlen) {
+        if (buf->strlen == AP_VARBUF_UNKNOWN)
+            buf->strlen = strlen(buf->buf);
         vec[i].iov_base = (void *)buf->buf;
-        vec[i].iov_len = (buf->strlen == AP_VARBUF_UNKNOWN) ? buf->avail
-                                                            : buf->strlen;
+        vec[i].iov_len = buf->strlen;
         i++;
     }
     if (append) {