From d59d732a10a4a2b9f18af6dfc3facf696108f31e Mon Sep 17 00:00:00 2001 From: Christian 'Ansuel' Marangi Date: Wed, 1 Jun 2022 14:25:32 +0200 Subject: client: fix compilation error with GCC 12 Using GCC 12 on an aarch64 target the following compilation error is printed. ninja: Entering directory `/home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360' [1/2] Building C object CMakeFiles/uhttpd.dir/client.c.o FAILED: CMakeFiles/uhttpd.dir/client.c.o /home/ansuel/openwrt/staging_dir/host/bin/ccache /home/ansuel/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-12.1.0_musl/bin/aarch64-openwrt-linux-musl-gcc -DHAVE_LUA -DHAVE_SHADOW -DHAVE_TLS -DHAVE_UBUS -DHAVE_UCODE -D_FILE_OFFSET_BITS=64 -Os -pipe -mcpu=cortex-a53 -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -fmacro-prefix-map=/home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360=uhttpd-2022-02-07-2f8b1360 -Wformat -Werror=format-security -DPIC -fPIC -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -DNDEBUG -Os -Wall -Werror -Wmissing-declarations --std=gnu99 -g3 -MD -MT CMakeFiles/uhttpd.dir/client.c.o -MF CMakeFiles/uhttpd.dir/client.c.o.d -o CMakeFiles/uhttpd.dir/client.c.o -c /home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360/client.c In function 'tls_redirect_check', inlined from 'client_header_complete' at client.c:306:7, inlined from 'client_parse_header' at client.c:338:3, inlined from 'client_header_cb' at client.c:502:2: client.c:269:22: error: 'strcmp' reading 1 or more bytes from a region of size 0 [-Werror=stringop-overread] 269 | if (!strcmp(blobmsg_name(cur), "URL")) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors ninja: build stopped: subcommand failed. Fix this by using the strncmp variant. Signed-off-by: Christian 'Ansuel' Marangi --- client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client.c b/client.c index 2be8f22..06336eb 100644 --- a/client.c +++ b/client.c @@ -263,10 +263,10 @@ static bool tls_redirect_check(struct client *cl) return true; blob_for_each_attr(cur, cl->hdr.head, rem) { - if (!strcmp(blobmsg_name(cur), "host")) + if (!strncmp(blobmsg_name(cur), "host", 4)) host = blobmsg_get_string(cur); - if (!strcmp(blobmsg_name(cur), "URL")) + if (!strncmp(blobmsg_name(cur), "URL", 3)) url = blobmsg_get_string(cur); if (url && host) -- cgit v1.2.3 From 8ba0b640aed7df39f2ce6d4c2182207b3294849e Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Fri, 1 Jan 2021 02:17:57 +0100 Subject: cmake: use variables and find_library for dependency Use FIND_LIBRARY to search the dependency and use variables to reference them in the CMakeLists file. Signed-off-by: Hauke Mehrtens [ improve commit description ] Signed-off-by: Christian Marangi --- CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 564842d..58eb6dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,9 +36,13 @@ IF(HAVE_SHADOW) ADD_DEFINITIONS(-DHAVE_SHADOW) ENDIF() +FIND_LIBRARY(ubox NAMES ubox) +FIND_LIBRARY(json_script NAMES json_script) +FIND_LIBRARY(blobmsg_json NAMES blobmsg_json) + ADD_EXECUTABLE(uhttpd ${SOURCES}) FIND_LIBRARY(libjson NAMES json-c json) -TARGET_LINK_LIBRARIES(uhttpd ubox dl json_script blobmsg_json ${libjson} ${LIBS}) +TARGET_LINK_LIBRARIES(uhttpd ${ubox} dl ${json_script} ${blobmsg_json} ${libjson} ${LIBS}) SET(PLUGINS "") IF(LUA_SUPPORT) @@ -78,10 +82,11 @@ IF(UCODE_SUPPORT) ENDIF() IF(UBUS_SUPPORT) + FIND_LIBRARY(ubus NAMES ubus) SET(PLUGINS ${PLUGINS} uhttpd_ubus) ADD_DEFINITIONS(-DHAVE_UBUS) ADD_LIBRARY(uhttpd_ubus MODULE ubus.c) - TARGET_LINK_LIBRARIES(uhttpd_ubus ubus ubox blobmsg_json ${libjson}) + TARGET_LINK_LIBRARIES(uhttpd_ubus ${ubus} ${ubox} ${blobmsg_json} ${libjson}) ENDIF() IF(PLUGINS) -- cgit v1.2.3 From f9db53870705f7c708e8fb93aed8dd636adafc94 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 2 Aug 2022 13:40:28 +0200 Subject: ucode: ignore exit exceptions A request handler might legitimately call `exit()`, don't raise a server error in this case. Signed-off-by: Jo-Philipp Wich Tested-by: Stijn Tintel --- ucode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ucode.c b/ucode.c index 69da3da..e76f441 100644 --- a/ucode.c +++ b/ucode.c @@ -195,6 +195,9 @@ uh_ucode_exception(uc_vm_t *vm, uc_exception_t *ex) { uc_value_t *ctx; + if (ex->type == EXCEPTION_EXIT) + return; + printf("Status: 500 Internal Server Error\r\n\r\n" "Exception while executing ucode program %s:\n", current_prefix->handler); -- cgit v1.2.3 From 145a309c54b7a9ff46fc588783f58804c23b09ab Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 2 Aug 2022 13:40:28 +0200 Subject: ucode: ignore exit exceptions A request handler might legitimately call `exit()`, don't raise a server error in this case. Signed-off-by: Jo-Philipp Wich --- ucode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ucode.c b/ucode.c index e76f441..c03b6f0 100644 --- a/ucode.c +++ b/ucode.c @@ -199,8 +199,8 @@ uh_ucode_exception(uc_vm_t *vm, uc_exception_t *ex) return; printf("Status: 500 Internal Server Error\r\n\r\n" - "Exception while executing ucode program %s:\n", - current_prefix->handler); + "Exception while executing ucode program %s:\n", + current_prefix->handler); switch (ex->type) { case EXCEPTION_SYNTAX: printf("Syntax error"); break; -- cgit v1.2.3 From 290ff883c69ac935ee3f22733d77d2a5a932f585 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 3 Aug 2022 00:23:54 +0200 Subject: relay: trigger close if in header read state with pending data In case a relay process exits without printing at least one newline, relay_close_if_done() will not close the relay context because there's still pending data in the ustream. Extend the relevant condition to only consider pending data if the relay context is not in the header parsing state anymore. Without this fix, requests triggering such a behaviour will never conclude. Signed-off-by: Jo-Philipp Wich --- relay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relay.c b/relay.c index 7331a0a..6db58ac 100644 --- a/relay.c +++ b/relay.c @@ -155,7 +155,7 @@ static void relay_close_if_done(struct uloop_timeout *timeout) while (ustream_poll(&r->sfd.stream)); - if (!(r->process_done || s->eof) || ustream_pending_data(s, false)) + if (!(r->process_done || s->eof) || (ustream_pending_data(s, false) && !r->header_cb)) return; uh_relay_close(r, r->ret); -- cgit v1.2.3 From c5eac5d27fb3967d796fe3c75f4cc1bdcd18ed01 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 10 Aug 2022 21:00:32 +0200 Subject: file: support using dynamic script handlers as error pages Rework the current request handler code to not require an error page path to be an actual file system entity. Signed-off-by: Jo-Philipp Wich --- file.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/file.c b/file.c index 1548900..ac781c1 100644 --- a/file.c +++ b/file.c @@ -49,6 +49,7 @@ struct deferred_request { struct dispatch_handler *d; struct client *cl; struct path_info pi; + char *url; bool called, path; }; @@ -631,7 +632,7 @@ static void uh_file_data(struct client *cl, struct path_info *pi, int fd) file_write_cb(cl); } -static bool __handle_file_request(struct client *cl, char *url); +static bool __handle_file_request(struct client *cl, char *url, bool is_error_handler); static void uh_file_request(struct client *cl, const char *url, struct path_info *pi, struct blob_attr **tb) @@ -684,7 +685,7 @@ error: req->redirect_status = 403; error_handler = alloca(strlen(conf.error_handler) + 1); strcpy(error_handler, conf.error_handler); - if (__handle_file_request(cl, error_handler)) + if (__handle_file_request(cl, error_handler, true)) return; } @@ -728,10 +729,8 @@ dispatch_find(const char *url, struct path_info *pi) } static void -uh_invoke_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi) +uh_invoke_script(struct client *cl, struct dispatch_handler *d, char *url, struct path_info *pi) { - char *url = blobmsg_data(blob_data(cl->hdr.head)); - n_requests++; d->handle_request(cl, url, pi); } @@ -752,7 +751,7 @@ static void uh_complete_request(struct client *cl) cl = dr->cl; dr->called = true; cl->dispatch.data_blocked = false; - uh_invoke_script(cl, dr->d, dr->path ? &dr->pi : NULL); + uh_invoke_script(cl, dr->d, dr->url, dr->path ? &dr->pi : NULL); client_poll_post_data(cl); ustream_poll(cl->us); } @@ -787,10 +786,10 @@ static int field_len(const char *ptr) _field(query) static void -uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi) +uh_defer_script(struct client *cl, struct dispatch_handler *d, char *url, struct path_info *pi) { struct deferred_request *dr; - char *_root, *_phys, *_name, *_info, *_query; + char *_url, *_root, *_phys, *_name, *_info, *_query; cl->dispatch.req_free = uh_free_pending_request; @@ -798,7 +797,7 @@ uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info /* allocate enough memory to duplicate all path_info strings in one block */ #undef _field #define _field(_name) &_##_name, field_len(pi->_name), - dr = calloc_a(sizeof(*dr), path_info_fields NULL); + dr = calloc_a(sizeof(*dr), &_url, strlen(url), path_info_fields NULL); memcpy(&dr->pi, pi, sizeof(*pi)); dr->path = true; @@ -808,11 +807,12 @@ uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info #define _field(_name) if (pi->_name) dr->pi._name = strcpy(_##_name, pi->_name); path_info_fields } else { - dr = calloc(1, sizeof(*dr)); + dr = calloc_a(sizeof(*dr), &_url, strlen(url), NULL); } cl->dispatch.req_data = dr; cl->dispatch.data_blocked = true; + dr->url = strcpy(_url, url); dr->cl = cl; dr->d = d; list_add(&dr->list, &pending_requests); @@ -825,13 +825,13 @@ uh_invoke_handler(struct client *cl, struct dispatch_handler *d, char *url, stru return d->handle_request(cl, url, pi); if (n_requests >= conf.max_script_requests) - return uh_defer_script(cl, d, pi); + return uh_defer_script(cl, d, url, pi); cl->dispatch.req_free = uh_complete_request; - uh_invoke_script(cl, d, pi); + uh_invoke_script(cl, d, url, pi); } -static bool __handle_file_request(struct client *cl, char *url) +static bool __handle_file_request(struct client *cl, char *url, bool is_error_handler) { static const struct blobmsg_policy hdr_policy[__HDR_MAX] = { [HDR_AUTHORIZATION] = { "authorization", BLOBMSG_TYPE_STRING }, @@ -846,6 +846,16 @@ static bool __handle_file_request(struct client *cl, char *url) struct path_info *pi; char *user, *pass, *auth; + if (is_error_handler) { + d = dispatch_find(url, NULL); + + if (d) { + uh_invoke_handler(cl, d, url, NULL); + + return true; + } + } + pi = uh_path_lookup(cl, url); if (!pi) return false; @@ -931,7 +941,7 @@ void uh_handle_request(struct client *cl) if (d) return uh_invoke_handler(cl, d, url, NULL); - if (__handle_file_request(cl, url)) + if (__handle_file_request(cl, url, false)) return; if (uh_handler_run(cl, &url, true)) { @@ -939,7 +949,7 @@ void uh_handle_request(struct client *cl) return; uh_handler_run(cl, &url, false); - if (__handle_file_request(cl, url)) + if (__handle_file_request(cl, url, false)) return; } @@ -947,7 +957,7 @@ void uh_handle_request(struct client *cl) if (conf.error_handler) { error_handler = alloca(strlen(conf.error_handler) + 1); strcpy(error_handler, conf.error_handler); - if (__handle_file_request(cl, error_handler)) + if (__handle_file_request(cl, error_handler, true)) return; } -- cgit v1.2.3 From 188dea23edf8b1646c662fa6ab8119f156da49a5 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 20:54:03 +0200 Subject: utils: accept '?' as path terminator in uh_path_match() When matching prefixes against the request URL, we should accept '?' as valid terminator, similar to '/' and '\0' since logically the query string is not part of the requested path. Signed-off-by: Jo-Philipp Wich --- utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.c b/utils.c index 142a410..6502d94 100644 --- a/utils.c +++ b/utils.c @@ -215,7 +215,7 @@ bool uh_path_match(const char *prefix, const char *url) if (strncmp(url, prefix, len) != 0) return false; - return url[len] == '/' || url[len] == 0; + return url[len] == '/' || url[len] == '?' || url[len] == 0; } char *uh_split_header(char *str) -- cgit v1.2.3 From 8cb3f85bdfef35e62f98d7d8b300eaedb6b1b20b Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 20:55:44 +0200 Subject: ucode: initialize default library search path Recent ucode versions require us to explicitly initialize the search path structure in the parser config. Signed-off-by: Jo-Philipp Wich --- ucode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ucode.c b/ucode.c index c03b6f0..01de012 100644 --- a/ucode.c +++ b/ucode.c @@ -231,6 +231,7 @@ uh_ucode_state_init(struct ucode_prefix *ucode) uc_vm_init(vm, &config); uc_stdlib_load(uc_vm_scope_get(vm)); + uc_search_path_init(&config.module_search_path); /* build uhttpd api table */ v = ucv_object_new(vm); -- cgit v1.2.3 From e3395cd90bed9b7b9fc319e79528fedcc0d947fe Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 21:30:18 +0200 Subject: ucode: initialize search path before VM init Since the VM initialization copies the search path into a runtime array, we must prepare the path beforehand. Fixes: 8cb3f85 ("ucode: initialize default library search path") Signed-off-by: Jo-Philipp Wich --- ucode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ucode.c b/ucode.c index 01de012..aa5d5b4 100644 --- a/ucode.c +++ b/ucode.c @@ -229,9 +229,9 @@ uh_ucode_state_init(struct ucode_prefix *ucode) uc_value_t *v; int exitcode; + uc_search_path_init(&config.module_search_path); uc_vm_init(vm, &config); uc_stdlib_load(uc_vm_scope_get(vm)); - uc_search_path_init(&config.module_search_path); /* build uhttpd api table */ v = ucv_object_new(vm); -- cgit v1.2.3