Changes with Apache 1.3.27
+ *) Back out an older patch for PR 9932, which had some incorrect
+ behavior. Instead, use a backport of the APR fix. This has
+ the nice effect that ap_snprintf() can now distinguish between
+ an output which was truncated, and an output which exactly
+ filled the buffer. [Jim Jagielski]
+
*) The cache in mod_proxy was incorrectly updating the Content-Length
value (to 0) from 304 responses when doing validation. Bugz#10128
[Paul Terry <paul.terry@gmx.net>, ast@domdv.de, Jim Jagielski]
* Process the format string until the entire string is exhausted, or
* the buffer fills. If the buffer fills then stop processing immediately
* (so no further %n arguments are processed), and return the buffer
- * length. In all cases the buffer is NUL terminated.
+ * length. In all cases the buffer is NUL terminated. The return value
+ * is the number of characters placed in the buffer, excluding the
+ * terminating NUL. All this implies that, at most, (len-1) characters
+ * will be copied over; if the return value is >= len, then truncation
+ * occured.
*
- * In no event does ap_snprintf return a negative number. It's not possible
- * to distinguish between an output which was truncated, and an output which
- * exactly filled the buffer.
+ * In no event does ap_snprintf return a negative number.
*/
API_EXPORT_NONSTD(int) ap_snprintf(char *buf, size_t len, const char *format,...)
__attribute__((format(printf,3,4)));
#endif
};
+#define AP_PSPRINTF_MIN_SIZE 32 /* Minimum size of allowable avail block */
+
static int psprintf_flush(ap_vformatter_buff *vbuff)
{
struct psprintf_data *ps = (struct psprintf_data *)vbuff;
#ifdef ALLOC_USE_MALLOC
- int size;
+ int cur_len, size;
char *ptr;
- size = (char *)ps->vbuff.curpos - ps->base;
- ptr = realloc(ps->base, 2*size);
+ cur_len = (char *)ps->vbuff.curpos - ps->base;
+ size = cur_len << 1;
+ if (size < AP_PSPRINTF_MIN_SIZE)
+ size = AP_PSPRINTF_MIN_SIZE;
+ ptr = realloc(ps->base, size);
if (ptr == NULL) {
fputs("Ouch! Out of memory!\n", stderr);
exit(1);
}
ps->base = ptr;
- ps->vbuff.curpos = ptr + size;
- ps->vbuff.endpos = ptr + 2*size - 1;
+ ps->vbuff.curpos = ptr + cur_len;
+ ps->vbuff.endpos = ptr + size - 1;
return 0;
#else
union block_hdr *blok;
union block_hdr *nblok;
- size_t cur_len;
+ size_t cur_len, size;
char *strp;
blok = ps->blok;
strp = ps->vbuff.curpos;
cur_len = strp - blok->h.first_avail;
+ size = cur_len << 1;
+ if (size < AP_PSPRINTF_MIN_SIZE)
+ size = AP_PSPRINTF_MIN_SIZE;
/* must try another blok */
(void) ap_acquire_mutex(alloc_mutex);
- nblok = new_block(2 * cur_len);
+ nblok = new_block(size);
(void) ap_release_mutex(alloc_mutex);
memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
ps->vbuff.curpos = nblok->h.first_avail + cur_len;
ps.vbuff.endpos = ps.blok->h.endp - 1; /* save one for NUL */
ps.got_a_new_block = 0;
+ if (ps.blok->h.first_avail == ps.blok->h.endp)
+ psprintf_flush(&ps.vbuff); /* ensure room for NUL */
ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
strp = ps.vbuff.curpos;