From 89a56392e3e83a0ceadb12fbf8406e0a595700a8 Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Tue, 29 Nov 2022 16:56:22 +0530 Subject: [PATCH] esp_http_server: fix wrong context pointer in httpd_req_cleanup function Added example which fails without the fix Closes https://github.com/espressif/esp-idf/issues/10265 --- components/esp_http_server/src/httpd_parse.c | 2 +- .../persistent_sockets/main/Kconfig.projbuild | 9 +++ .../persistent_sockets/main/main.c | 61 +++++++++++++++++++ .../pytest_http_server_persistence.py | 10 +++ .../persistent_sockets/sdkconfig.ci | 1 + 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c index a22e741c1d..453ef78c29 100644 --- a/components/esp_http_server/src/httpd_parse.c +++ b/components/esp_http_server/src/httpd_parse.c @@ -695,7 +695,7 @@ static void httpd_req_cleanup(httpd_req_t *r) /* Check if the context has changed and needs to be cleared */ if ((r->ignore_sess_ctx_changes == false) && (ra->sd->ctx != r->sess_ctx)) { - httpd_sess_free_ctx(ra->sd->ctx, ra->sd->free_ctx); + httpd_sess_free_ctx(&ra->sd->ctx, ra->sd->free_ctx); } #if CONFIG_HTTPD_WS_SUPPORT diff --git a/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild b/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild new file mode 100644 index 0000000000..8c201d68f7 --- /dev/null +++ b/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Example Configuration" + + config EXAMPLE_SESSION_CTX_HANDLERS + bool "Update session ctx from another handler" + default n + help + Feature to show how session ctx can be manipulated by other handlers. + +endmenu diff --git a/examples/protocols/http_server/persistent_sockets/main/main.c b/examples/protocols/http_server/persistent_sockets/main/main.c index e70745b34f..92be4422a1 100644 --- a/examples/protocols/http_server/persistent_sockets/main/main.c +++ b/examples/protocols/http_server/persistent_sockets/main/main.c @@ -99,6 +99,47 @@ static esp_err_t adder_get_handler(httpd_req_t *req) return ESP_OK; } +#if CONFIG_EXAMPLE_SESSION_CTX_HANDLERS +// login and logout handler are created to test the server functionality to delete the older sess_ctx if it is changed from another handler. +// login handler creates a new sess_ctx +static esp_err_t login_handler(httpd_req_t *req) +{ + /* Log total visitors */ + unsigned *visitors = (unsigned *)req->user_ctx; + ESP_LOGI(TAG, "/login visitor count = %d", ++(*visitors)); + + char outbuf[50]; + + /* Create session's context if not already available */ + if (! req->sess_ctx) { + ESP_LOGI(TAG, "/login GET allocating new session"); + req->sess_ctx = malloc(sizeof(int)); + if (!req->sess_ctx) { + return ESP_ERR_NO_MEM; + } + *(int *)req->sess_ctx = 1; + } + ESP_LOGI(TAG, "/login GET handler send %d", *(int *)req->sess_ctx); + + /* Respond with the accumulated value */ + snprintf(outbuf, sizeof(outbuf),"%d", *((int *)req->sess_ctx)); + httpd_resp_send(req, outbuf, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} + +// This handler sets sess_ctx to NULL. +static esp_err_t logout_handler(httpd_req_t *req) +{ + ESP_LOGI(TAG, "Logging out"); + // Setting sess_ctx to NULL here. This is done to test the server functionality to free the older sesss_ctx if it is changed by some handler. + req->sess_ctx = NULL; + char outbuf[50]; + snprintf(outbuf, sizeof(outbuf),"%d", 1); + httpd_resp_send(req, outbuf, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} +#endif // CONFIG_EXAMPLE_SESSION_CTX_HANDLERS + /* This handler resets the value of the accumulator */ static esp_err_t adder_put_handler(httpd_req_t *req) { @@ -155,6 +196,22 @@ static const httpd_uri_t adder_get = { .user_ctx = &visitors }; +#if CONFIG_EXAMPLE_SESSION_CTX_HANDLERS +static const httpd_uri_t login = { + .uri = "/login", + .method = HTTP_GET, + .handler = login_handler, + .user_ctx = &visitors +}; + +static const httpd_uri_t logout = { + .uri = "/logout", + .method = HTTP_GET, + .handler = logout_handler, + .user_ctx = &visitors +}; +#endif // CONFIG_EXAMPLE_SESSION_CTX_HANDLERS + static const httpd_uri_t adder_put = { .uri = "/adder", .method = HTTP_PUT, @@ -173,6 +230,10 @@ static httpd_handle_t start_webserver(void) // Set URI handlers ESP_LOGI(TAG, "Registering URI handlers"); httpd_register_uri_handler(server, &adder_get); +#if CONFIG_EXAMPLE_SESSION_CTX_HANDLERS + httpd_register_uri_handler(server, &login); + httpd_register_uri_handler(server, &logout); +#endif // CONFIG_EXAMPLE_SESSION_CTX_HANDLERS httpd_register_uri_handler(server, &adder_put); httpd_register_uri_handler(server, &adder_post); return server; diff --git a/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py b/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py index c0514e54e2..efd15fb1b8 100644 --- a/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py +++ b/examples/protocols/http_server/persistent_sockets/pytest_http_server_persistence.py @@ -60,6 +60,16 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None: visitor = 0 adder = 0 + # Test login and logout + if client.getreq(conn, '/login').decode() != str(1): + raise RuntimeError + visitor += 1 + dut.expect('/login visitor count = ' + str(visitor), timeout=30) + dut.expect('/login GET handler send ' + str(1), timeout=30) + if client.getreq(conn, '/logout').decode() != str(1): + raise RuntimeError + dut.expect('Logging out', timeout=30) + # Test PUT request and initialize session context num = random.randint(0,100) client.putreq(conn, '/adder', str(num)) diff --git a/examples/protocols/http_server/persistent_sockets/sdkconfig.ci b/examples/protocols/http_server/persistent_sockets/sdkconfig.ci index 543e69e76e..5f6f00a552 100644 --- a/examples/protocols/http_server/persistent_sockets/sdkconfig.ci +++ b/examples/protocols/http_server/persistent_sockets/sdkconfig.ci @@ -1 +1,2 @@ CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y +CONFIG_EXAMPLE_SESSION_CTX_HANDLERS=y