diff --git a/CMakeLists.txt b/CMakeLists.txt index 64c0e5749..ba4f3f9a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ option(LWS_WITH_EXPORT_LWSTARGETS "Export libwebsockets CMake targets. Disable option(LWS_REPRODUCIBLE "Build libwebsockets reproducible. It removes the build user and hostname from the build" ON) option(LWS_WITH_MINIMAL_EXAMPLES "Also build the normally standalone minimal examples, for QA" OFF) option(LWS_WITH_LWSAC "lwsac Chunk Allocation api" ON) +option(LWS_WITH_ASAN "Build with gcc runtime sanitizer options enabled (needs libasan)" OFF) # # End of user settings # @@ -1183,6 +1184,10 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage -O0") endif() + if (LWS_WITH_ASAN) + set (ASAN_FLAGS "-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak -fsanitize=undefined -fsanitize-address-use-after-scope -fsanitize-undefined-trap-on-error") + message("Enabling ASAN") + endif() if (CMAKE_BUILD_TYPE MATCHES "DEBUG") set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS}") else() @@ -1190,7 +1195,7 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID endif() if (UNIX AND NOT LWS_WITH_ESP32) - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) + set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) else() set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() diff --git a/READMEs/README.coding.md b/READMEs/README.coding.md index 74c575651..7149f6665 100644 --- a/READMEs/README.coding.md +++ b/READMEs/README.coding.md @@ -379,7 +379,19 @@ If you are not building with _DEBUG defined, ie, without this then log levels below notice do not actually get compiled in. +@section asan Building with ASAN +Under GCC you can select for the build to be instrumented with the Address +Sanitizer, using `cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_ASAN=1`. LWS is routinely run during development with valgrind, but ASAN is capable of finding different issues at runtime, like operations which are not strictly defined in the C +standard and depend on platform behaviours. + +Run your application like this + +``` + $ sudo ASAN_OPTIONS=verbosity=2:halt_on_error=1 /usr/local/bin/lwsws +``` + +and attach gdb to catch the place it halts. @section extpoll External Polling Loop support diff --git a/lib/core/private.h b/lib/core/private.h index 706b0427c..857366a6a 100644 --- a/lib/core/private.h +++ b/lib/core/private.h @@ -771,7 +771,7 @@ enum { LWS_EV_START = (1 << 2), LWS_EV_STOP = (1 << 3), - LWS_EV_PREPARE_DELETION = (1 << 31), + LWS_EV_PREPARE_DELETION = (1u << 31), }; diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 69f2df2c3..2c43fd0c4 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -1202,7 +1202,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi) wsi->h2.initialized = 1; } - if (h2n->collected_priority && (h2n->dep & ~(1 << 31)) == h2n->sid) { + if (h2n->collected_priority && (h2n->dep & ~(1u << 31)) == h2n->sid) { lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "depends on own sid"); return 0; } @@ -1513,7 +1513,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi) break; case LWS_H2_FRAME_TYPE_WINDOW_UPDATE: - h2n->hpack_e_dep &= ~(1 << 31); + h2n->hpack_e_dep &= ~(1u << 31); lwsl_info("WINDOW_UPDATE: sid %d %u (0x%x)\n", h2n->sid, h2n->hpack_e_dep, h2n->hpack_e_dep); @@ -1904,7 +1904,7 @@ do_windows: lwsl_info("PRIORITY: dep 0x%x, weight 0x%02X\n", h2n->dep, h2n->weight_temp); - if ((h2n->dep & ~(1 << 31)) == h2n->sid) { + if ((h2n->dep & ~(1u << 31)) == h2n->sid) { lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "cant depend on own sid"); break;