From c0b1fa0983fdc8a7cc13647b8ceb624e7ffffd70 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Mon, 19 Aug 2024 19:54:42 +0100 Subject: [PATCH] Fix new Location: handling for non-origin-form request-target. * src/ne_request.c (ne_get_response_location): Rewrite to use target URI correctly determined from get_request_target_uri, fixing non-origin-form cases. * test/redirect.c (redirects): Test for non-origin-form targets. --- src/ne_request.c | 24 +++++++++++++++--------- test/redirect.c | 4 ++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/ne_request.c b/src/ne_request.c index bf6c986b..781d77f0 100644 --- a/src/ne_request.c +++ b/src/ne_request.c @@ -762,24 +762,30 @@ static void free_response_headers(ne_request *req) ne_uri *ne_get_response_location(ne_request *req, const char *fragment) { const char *location; - ne_uri dest, base, *ret; + ne_uri dest, base, *ret = NULL; location = get_response_header_hv(req, HH_HV_LOCATION, "location"); if (location == NULL) return NULL; + memset(&base, 0, sizeof base); + memset(&dest, 0, sizeof dest); + + /* Location is a URI-reference (RFC9110ẞ10.2.2) relative to the + * request target URI; determine each of these then resolve. */ + /* Parse the Location header */ if (ne_uri_parse(location, &dest) || !dest.path) { - ne_set_error(req->session, _("Could not parse redirect " + ne_set_error(req->session, _("Could not parse redirect " "destination URL")); - return NULL; + goto fail; } - /* Location is a URI-reference (RFC9110ẞ10.2.2) relative to the - * request target URI; create that base URI: */ - memset(&base, 0, sizeof base); - ne_fill_server_uri(req->session, &base); - base.path = req->target; + if (get_request_target_uri(req, &base)) { + ne_set_error(req->session, _("Could not parse redirect " + "destination URL")); + goto fail; + } ret = ne_malloc(sizeof *ret); ne_uri_resolve(&base, &dest, ret); @@ -789,7 +795,7 @@ ne_uri *ne_get_response_location(ne_request *req, const char *fragment) ret->fragment = ne_strdup(fragment); } - base.path = NULL; /* owned by ne_request object, don't free */ +fail: ne_uri_free(&base); ne_uri_free(&dest); diff --git a/test/redirect.c b/test/redirect.c index 12ccae9d..0a6fa703 100644 --- a/test/redirect.c +++ b/test/redirect.c @@ -144,6 +144,10 @@ static int redirects(void) /* all 3xx should get NE_REDIRECT. */ {PATH, 399, DEST, DEST, NULL}, + /* Handling of various request-target cases. */ + {"*", 307, "/fish#food", "/fish#food", NULL}, + {"ftp://example.com/fish", 307, "/fish#food", "ftp://example.com/fish#food", NULL}, + /* More relative URIs: */ {"/blah", 307, "//example.com:8080/fish#food", "http://example.com:8080/fish#food", NULL}, {"/blah", 307, "#food", "/blah#food", NULL},