From 0b120410ed0fc372f0a7bacef5275d36b73fd1c5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 9 Sep 2026 10:13:00 +0000 Subject: [PATCH 1/2] fix(build): avoid redefining _FORTIFY_SOURCE OpenWrt SDK CFLAGS and Debian/Ubuntu gcc already define _FORTIFY_SOURCE. Forcing =2 on every translation unit produced ": warning: _FORTIFY_SOURCE redefined" on all OpenWrt architectures and could weaken a higher distro default. Probe the toolchain first and only add level 2 when nothing is predefined. Co-authored-by: Stackie Jia --- CMakeLists.txt | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88189902..cf65ecb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,8 +147,37 @@ if(PLATFORM_LINUX OR PLATFORM_FREEBSD) target_compile_options(rtp2httpd PRIVATE -fstack-protector-strong) # _FORTIFY_SOURCE requires optimization >= -O1 if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - target_compile_definitions(rtp2httpd PRIVATE _FORTIFY_SOURCE=2) + # Toolchains often already define this macro: + # OpenWrt CFLAGS: -D_FORTIFY_SOURCE=1 + # Debian/Ubuntu gcc spec: -D_FORTIFY_SOURCE=3 (when optimizing) + # Forcing -D_FORTIFY_SOURCE=2 on top of that produces + # : warning: "_FORTIFY_SOURCE" redefined + # and can silently weaken a higher distro default. Only add level 2 + # when the compiler/flags do not already provide one. + include(CheckCSourceCompiles) + set(_rtp2httpd_saved_required_flags "${CMAKE_REQUIRED_FLAGS}") + set(_rtp2httpd_saved_required_quiet "${CMAKE_REQUIRED_QUIET}") + set(CMAKE_REQUIRED_QUIET TRUE) + # -O2 lets gcc spec files inject their default _FORTIFY_SOURCE. + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -O2") + check_c_source_compiles( + "#ifndef _FORTIFY_SOURCE\n#error \"_FORTIFY_SOURCE not predefined\"\n#endif\nint main(void) { return 0; }\n" + RTP2HTTPD_HAS_PREDEFINED_FORTIFY_SOURCE) + set(CMAKE_REQUIRED_FLAGS "${_rtp2httpd_saved_required_flags}") + set(CMAKE_REQUIRED_QUIET "${_rtp2httpd_saved_required_quiet}") + unset(_rtp2httpd_saved_required_flags) + unset(_rtp2httpd_saved_required_quiet) + if(NOT RTP2HTTPD_HAS_PREDEFINED_FORTIFY_SOURCE) + target_compile_definitions(rtp2httpd PRIVATE _FORTIFY_SOURCE=2) + set(RTP2HTTPD_FORTIFY_SOURCE "2 (project)") + else() + set(RTP2HTTPD_FORTIFY_SOURCE "toolchain default") + endif() + else() + set(RTP2HTTPD_FORTIFY_SOURCE "disabled (Debug)") endif() +else() + set(RTP2HTTPD_FORTIFY_SOURCE "not applied") endif() # ── Libraries ─────────────────────────────────────────────────────── @@ -177,5 +206,6 @@ message(STATUS " Platform: ${CMAKE_SYSTEM_NAME}") message(STATUS " Compiler: ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}") message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") message(STATUS " Aggressive opt: ${ENABLE_AGGRESSIVE_OPT}") +message(STATUS " Fortify: ${RTP2HTTPD_FORTIFY_SOURCE}") message(STATUS " Install prefix: ${CMAKE_INSTALL_PREFIX}") message(STATUS "") From f201675e74dde1777d451b1c000e588c478d1490 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 9 Sep 2026 10:13:00 +0000 Subject: [PATCH 2/2] fix(build): detect finite doubles without isfinite() Release builds enable -ffast-math, which implies -ffinite-math-only. isfinite() is then treated as always-true and Clang warns with -Wnan-infinity-disabled. Inspect IEEE-754 exponent bits instead so Scale/NPT parsing still rejects NaN and Inf. Co-authored-by: Stackie Jia --- src/rtsp.c | 8 ++++---- src/stream.c | 5 ++--- src/utils.h | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/rtsp.c b/src/rtsp.c index 475ff575..3c327a2a 100644 --- a/src/rtsp.c +++ b/src/rtsp.c @@ -2965,7 +2965,7 @@ static void rtsp_parse_play_metadata(rtsp_session_t *session, const struct phr_h scale = strtod(scale_buf, &end); while (end && (*end == ' ' || *end == '\t')) end++; - if (end != scale_buf && end && *end == '\0' && errno != ERANGE && isfinite(scale)) { + if (end != scale_buf && end && *end == '\0' && errno != ERANGE && double_is_finite(scale)) { metadata->playback_scale = scale; metadata->playback_scale_known = 1; } @@ -3072,7 +3072,7 @@ static int rtsp_parse_npt_time(const char *value, const char **end_out, double * errno = 0; first_component = strtod(value, &component_end); - if (component_end == value || errno == ERANGE || !isfinite(first_component) || first_component < 0.0) + if (component_end == value || errno == ERANGE || !double_is_finite(first_component) || first_component < 0.0) return -1; if (*component_end != ':') { @@ -3099,11 +3099,11 @@ static int rtsp_parse_npt_time(const char *value, const char **end_out, double * errno = 0; seconds = strtod(seconds_start, &seconds_end); - if (seconds_end == seconds_start || errno == ERANGE || !isfinite(seconds) || seconds < 0.0 || seconds >= 60.0) + if (seconds_end == seconds_start || errno == ERANGE || !double_is_finite(seconds) || seconds < 0.0 || seconds >= 60.0) return -1; double total = first_component * 3600.0 + (double)minutes * 60.0 + seconds; - if (!isfinite(total)) + if (!double_is_finite(total)) return -1; *end_out = seconds_end; diff --git a/src/stream.c b/src/stream.c index 3020bcd4..323b6d77 100644 --- a/src/stream.c +++ b/src/stream.c @@ -13,7 +13,6 @@ #include "status.h" #include "utils.h" #include -#include #include #include #include @@ -260,7 +259,7 @@ void stream_send_http_headers(connection_t *conn, const char *content_type, cons metadata->upstream_payload) < 0; /* A value we cannot render exactly is dropped rather than approximated. */ - if (metadata->playback_scale_known && isfinite(metadata->playback_scale)) { + if (metadata->playback_scale_known && double_is_finite(metadata->playback_scale)) { if (stream_metadata_format_number(metadata->playback_scale, number, sizeof(number)) == 0) failed |= stream_metadata_append_header(headers, sizeof(headers), &length, stream_metadata_header_names[STREAM_HDR_PLAYBACK_SCALE], number) < 0; @@ -272,7 +271,7 @@ void stream_send_http_headers(connection_t *conn, const char *content_type, cons stream_metadata_header_names[STREAM_HDR_PLAYBACK_RANGE], metadata->playback_range) < 0; } - if (metadata->media_duration_known && isfinite(metadata->media_duration)) { + if (metadata->media_duration_known && double_is_finite(metadata->media_duration)) { if (stream_metadata_format_number(metadata->media_duration, number, sizeof(number)) == 0) failed |= stream_metadata_append_header(headers, sizeof(headers), &length, stream_metadata_header_names[STREAM_HDR_MEDIA_DURATION], number) < 0; diff --git a/src/utils.h b/src/utils.h index 32bfbd3a..d40d642d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -49,6 +49,22 @@ int64_t get_realtime_ms(void); #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) +/** + * Return 1 if `value` is a finite IEEE-754 double (not NaN or Inf). + * + * Inspects exponent bits instead of calling isfinite(). With -ffast-math / + * -ffinite-math-only, isfinite() is treated as always-true and Clang emits + * -Wnan-infinity-disabled. + */ +static inline int double_is_finite(double value) { + union { + double d; + uint64_t u; + } conv; + conv.d = value; + return ((conv.u >> 52) & 0x7ffULL) != 0x7ffULL; +} + /** * Set socket receive buffer size, trying SO_RCVBUFFORCE first. * SO_RCVBUFFORCE can exceed system limits but requires CAP_NET_ADMIN.