summaryrefslogtreecommitdiffstats
path: root/modules/cache/mod_cache_socache.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:27 +0000
commitc54018b07a9085c0a3aedbc2bd01a85a3b3e20cf (patch)
treef6e1d6fcf9f6db3794c418b2f89ecf9e08ff41c8 /modules/cache/mod_cache_socache.c
parentAdding debian version 2.4.38-3+deb10u10. (diff)
downloadapache2-c54018b07a9085c0a3aedbc2bd01a85a3b3e20cf.tar.xz
apache2-c54018b07a9085c0a3aedbc2bd01a85a3b3e20cf.zip
Merging upstream version 2.4.59.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/cache/mod_cache_socache.c')
-rw-r--r--modules/cache/mod_cache_socache.c98
1 files changed, 49 insertions, 49 deletions
diff --git a/modules/cache/mod_cache_socache.c b/modules/cache/mod_cache_socache.c
index 0d76760..5f9e1d6 100644
--- a/modules/cache/mod_cache_socache.c
+++ b/modules/cache/mod_cache_socache.c
@@ -18,6 +18,12 @@
#include "apr_file_io.h"
#include "apr_strings.h"
#include "apr_buckets.h"
+
+#include "apr_version.h"
+#if !APR_VERSION_AT_LEAST(2,0,0)
+#include "apu_version.h"
+#endif
+
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
@@ -217,8 +223,8 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r,
while (apr_isspace(buffer[colon]) && (colon < *slider)) {
colon++;
}
- apr_table_addn(table, apr_pstrndup(r->pool, (const char *) buffer
- + key, len - key), apr_pstrndup(r->pool,
+ apr_table_addn(table, apr_pstrmemdup(r->pool, (const char *) buffer
+ + key, len - key), apr_pstrmemdup(r->pool,
(const char *) buffer + colon, *slider - colon));
(*slider)++;
if (buffer[*slider] == '\n') {
@@ -298,11 +304,11 @@ static const char* regen_key(apr_pool_t *p, apr_table_t *headers,
* HTTP URI's (3.2.3) [host and scheme are insensitive]
* HTTP method (5.1.1)
* HTTP-date values (3.3.1)
- * 3.7 Media Types [exerpt]
+ * 3.7 Media Types [excerpt]
* The type, subtype, and parameter attribute names are case-
* insensitive. Parameter values might or might not be case-sensitive,
* depending on the semantics of the parameter name.
- * 4.20 Except [exerpt]
+ * 4.20 Except [excerpt]
* Comparison of expectation values is case-insensitive for unquoted
* tokens (including the 100-continue token), and is case-sensitive for
* quoted-string expectation-extensions.
@@ -429,6 +435,14 @@ static int create_entity(cache_handle_t *h, request_rec *r, const char *key,
return OK;
}
+static apr_status_t sobj_body_pre_cleanup(void *baton)
+{
+ cache_socache_object_t *sobj = baton;
+ apr_brigade_cleanup(sobj->body);
+ sobj->body = NULL;
+ return APR_SUCCESS;
+}
+
static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
{
cache_socache_dir_conf *dconf =
@@ -463,6 +477,7 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
* about for the lifetime of the response.
*/
apr_pool_create(&sobj->pool, r->pool);
+ apr_pool_tag(sobj->pool, "mod_cache_socache (open_entity)");
sobj->buffer = apr_palloc(sobj->pool, dconf->max);
sobj->buffer_len = dconf->max;
@@ -648,36 +663,25 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
}
/* Retrieve the body if we have one */
- sobj->body = apr_brigade_create(r->pool, r->connection->bucket_alloc);
len = buffer_len - slider;
-
- /*
- * Optimisation: if the body is small, we want to make a
- * copy of the body and free the temporary pool, as we
- * don't want large blocks of unused memory hanging around
- * to the end of the response. In contrast, if the body is
- * large, we would rather leave the body where it is in the
- * temporary pool, and save ourselves the copy.
- */
- if (len * 2 > dconf->max) {
+ if (len > 0) {
apr_bucket *e;
-
- /* large - use the brigade as is, we're done */
- e = apr_bucket_immortal_create((const char *) sobj->buffer + slider,
- len, r->connection->bucket_alloc);
-
+ /* Create the body brigade later concatenated to the output filters'
+ * brigade by recall_body(). Since sobj->buffer (the data) point to
+ * sobj->pool (a subpool of r->pool), be safe by using a pool bucket
+ * which can morph to heap if sobj->pool is destroyed while the bucket
+ * is still alive. But if sobj->pool gets destroyed while the bucket is
+ * still in sobj->body (i.e. recall_body() was never called), we don't
+ * need to morph to something just about to be freed, so a pre_cleanup
+ * will take care of cleaning up sobj->body before this happens (and is
+ * a noop otherwise).
+ */
+ sobj->body = apr_brigade_create(sobj->pool, r->connection->bucket_alloc);
+ apr_pool_pre_cleanup_register(sobj->pool, sobj, sobj_body_pre_cleanup);
+ e = apr_bucket_pool_create((const char *) sobj->buffer + slider, len,
+ sobj->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(sobj->body, e);
}
- else {
-
- /* small - make a copy of the data... */
- apr_brigade_write(sobj->body, NULL, NULL, (const char *) sobj->buffer
- + slider, len);
-
- /* ...and get rid of the large memory buffer */
- apr_pool_destroy(sobj->pool);
- sobj->pool = NULL;
- }
/* make the configuration stick */
h->cache_obj = obj;
@@ -766,13 +770,9 @@ static apr_status_t recall_body(cache_handle_t *h, apr_pool_t *p,
apr_bucket_brigade *bb)
{
cache_socache_object_t *sobj = (cache_socache_object_t*) h->cache_obj->vobj;
- apr_bucket *e;
- e = APR_BRIGADE_FIRST(sobj->body);
-
- if (e != APR_BRIGADE_SENTINEL(sobj->body)) {
- APR_BUCKET_REMOVE(e);
- APR_BRIGADE_INSERT_TAIL(bb, e);
+ if (sobj->body) {
+ APR_BRIGADE_CONCAT(bb, sobj->body);
}
return APR_SUCCESS;
@@ -807,6 +807,7 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r,
: obj->info.expire + dconf->mintime;
apr_pool_create(&sobj->pool, r->pool);
+ apr_pool_tag(sobj->pool, "mod_cache_socache (store_headers)");
sobj->buffer = apr_palloc(sobj->pool, dconf->max);
sobj->buffer_len = dconf->max;
@@ -1051,7 +1052,8 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r,
/* Was this the final bucket? If yes, perform sanity checks.
*/
if (seen_eos) {
- const char *cl_header = apr_table_get(r->headers_out, "Content-Length");
+ const char *cl_header;
+ apr_off_t cl;
if (r->connection->aborted || r->no_cache) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02380)
@@ -1062,18 +1064,16 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r,
sobj->pool = NULL;
return APR_EGENERAL;
}
- if (cl_header) {
- apr_off_t cl;
- char *cl_endp;
- if (apr_strtoff(&cl, cl_header, &cl_endp, 10) != APR_SUCCESS
- || *cl_endp != '\0' || cl != sobj->body_length) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381)
- "URL %s didn't receive complete response, not caching",
- h->cache_obj->key);
- apr_pool_destroy(sobj->pool);
- sobj->pool = NULL;
- return APR_EGENERAL;
- }
+
+ cl_header = apr_table_get(r->headers_out, "Content-Length");
+ if (cl_header && (!ap_parse_strict_length(&cl, cl_header)
+ || cl != sobj->body_length)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381)
+ "URL %s didn't receive complete response, not caching",
+ h->cache_obj->key);
+ apr_pool_destroy(sobj->pool);
+ sobj->pool = NULL;
+ return APR_EGENERAL;
}
/* All checks were fine, we're good to go when the commit comes */