mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
Merge branch 'fix/fix_ws_server_subprotocols_null_dereference_v5.5' into 'release/v5.5'
fix: fixes websocket server possible null dereference (v5.5) See merge request espressif/esp-idf!46918
This commit is contained in:
@@ -844,7 +844,8 @@ esp_err_t httpd_sess_set_pending_override(httpd_handle_t hd, int sockfd, httpd_p
|
||||
* @note
|
||||
* - This function is necessary in order to handle multiple requests simultaneously.
|
||||
* See examples/async_requests for example usage.
|
||||
* - You must call httpd_req_async_handler_complete() when you are done with the request.
|
||||
* - You must call httpd_req_async_handler_complete() when you are done with the request
|
||||
* and also on any error conditions.
|
||||
*
|
||||
* @param[in] r The request to create an async copy of
|
||||
* @param[out] out A newly allocated request which can be used on an async thread
|
||||
|
||||
@@ -213,6 +213,9 @@ esp_err_t httpd_unregister_uri_handler(httpd_handle_t handle,
|
||||
ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, hd->hd_calls[i]->uri);
|
||||
|
||||
free((char*)hd->hd_calls[i]->uri);
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
free((char*)hd->hd_calls[i]->supported_subprotocol);
|
||||
#endif // CONFIG_HTTPD_WS_SUPPORT
|
||||
free(hd->hd_calls[i]);
|
||||
hd->hd_calls[i] = NULL;
|
||||
|
||||
@@ -251,6 +254,9 @@ esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char *uri)
|
||||
ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, uri);
|
||||
|
||||
free((char*)hd->hd_calls[i]->uri);
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
free((char*)hd->hd_calls[i]->supported_subprotocol);
|
||||
#endif // CONFIG_HTTPD_WS_SUPPORT
|
||||
free(hd->hd_calls[i]);
|
||||
hd->hd_calls[i] = NULL;
|
||||
found = true;
|
||||
@@ -282,6 +288,9 @@ void httpd_unregister_all_uri_handlers(struct httpd_data *hd)
|
||||
ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, hd->hd_calls[i]->uri);
|
||||
|
||||
free((char*)hd->hd_calls[i]->uri);
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
free((char*)hd->hd_calls[i]->supported_subprotocol);
|
||||
#endif // CONFIG_HTTPD_WS_SUPPORT
|
||||
free(hd->hd_calls[i]);
|
||||
hd->hd_calls[i] = NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -82,12 +82,15 @@ static bool httpd_ws_get_response_subprotocol(const char *supported_subprotocol,
|
||||
/* Get first subprotocol from comma separated list */
|
||||
char *rest = NULL;
|
||||
char *s = strtok_r(subprotocol, ", ", &rest);
|
||||
do {
|
||||
if (strncmp(s, supported_subprotocol, sizeof(subprotocol)) == 0) {
|
||||
int supported_subprotocol_len = strlen(supported_subprotocol);
|
||||
while (s != NULL) {
|
||||
if (strlen(s) == supported_subprotocol_len &&
|
||||
strncmp(s, supported_subprotocol, supported_subprotocol_len) == 0) {
|
||||
ESP_LOGD(TAG, "Requested subprotocol supported: %s", s);
|
||||
return true;
|
||||
}
|
||||
} while ((s = strtok_r(NULL, ", ", &rest)) != NULL);
|
||||
s = strtok_r(NULL, ", ", &rest);
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Sec-WebSocket-Protocol %s not supported, supported subprotocol is %s", subprotocol, supported_subprotocol);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_http_server.h>
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
@@ -31,6 +32,21 @@ httpd_uri_t handler_limit_uri (char* path)
|
||||
return uri;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
static httpd_uri_t handler_limit_ws_uri(char *path, const char *subprotocol)
|
||||
{
|
||||
httpd_uri_t uri = {
|
||||
.uri = path,
|
||||
.method = HTTP_GET,
|
||||
.handler = null_func,
|
||||
.user_ctx = NULL,
|
||||
.is_websocket = true,
|
||||
.supported_subprotocol = subprotocol,
|
||||
};
|
||||
return uri;
|
||||
}
|
||||
#endif /* CONFIG_HTTPD_WS_SUPPORT */
|
||||
|
||||
static inline unsigned num_digits(unsigned x)
|
||||
{
|
||||
unsigned digits = 1;
|
||||
@@ -81,6 +97,36 @@ void test_handler_limit(httpd_handle_t hd)
|
||||
TEST_ASSERT(httpd_unregister_uri_handler(hd, uris[i].uri, uris[i].method) == ESP_OK);
|
||||
}
|
||||
basic_sanity = false;
|
||||
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
/* --- WS subprotocol memory leak check ---
|
||||
* Each registration strdup's the supported_subprotocol string.
|
||||
* Verify that unregistration frees it (expected leak per handler:
|
||||
* strlen(subprotocol) + 1 bytes if the bug is present).
|
||||
*/
|
||||
char ws_paths[HTTPD_TEST_MAX_URI_HANDLERS][8];
|
||||
httpd_uri_t ws_uris[HTTPD_TEST_MAX_URI_HANDLERS];
|
||||
const char *subprotocol = "chat";
|
||||
|
||||
for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS; i++) {
|
||||
sprintf(ws_paths[i], "/ws%d", i);
|
||||
ws_uris[i] = handler_limit_ws_uri(ws_paths[i], subprotocol);
|
||||
}
|
||||
|
||||
size_t heap_before = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
|
||||
for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS; i++) {
|
||||
TEST_ASSERT(httpd_register_uri_handler(hd, &ws_uris[i]) == ESP_OK);
|
||||
}
|
||||
for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS; i++) {
|
||||
TEST_ASSERT(httpd_unregister_uri_handler(hd, ws_uris[i].uri, ws_uris[i].method) == ESP_OK);
|
||||
}
|
||||
|
||||
size_t heap_after = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int leaked = (int)heap_before - (int)heap_after;
|
||||
|
||||
TEST_ASSERT_MESSAGE(leaked <= 0, "Heap leaked after WS handler unregister");
|
||||
#endif /* CONFIG_HTTPD_WS_SUPPORT */
|
||||
}
|
||||
|
||||
/********************* Test Handler Limit End *******************/
|
||||
@@ -100,7 +146,7 @@ httpd_handle_t test_httpd_start(uint16_t id)
|
||||
|
||||
/* Currently this only tests for the number of tasks.
|
||||
* Heap leakage is not tested as LWIP allocates memory
|
||||
* which may not be freed immedietly causing erroneous
|
||||
* which may not be freed immediately causing erroneous
|
||||
* evaluation. Another test to implement would be the
|
||||
* monitoring of open sockets, but LWIP presently provides
|
||||
* no such API for getting the number of open sockets.
|
||||
|
||||
@@ -7,3 +7,4 @@ CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y
|
||||
CONFIG_COMPILER_STACK_CHECK=y
|
||||
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_HTTPD_WS_SUPPORT=y
|
||||
|
||||
Reference in New Issue
Block a user