Merge feat/hardening-misc: lazy protocol debug escaping, log_debug_enabled

This commit is contained in:
2026-09-12 18:08:56 +02:00
4 changed files with 30 additions and 2 deletions
+4
View File
@@ -27,6 +27,10 @@ uint32_t get_log_debug_flags(void) {
return current_debug_flags; return current_debug_flags;
} }
bool log_debug_enabled(LogDebugFlag flag) {
return current_log_level <= LOG_LEVEL_DEBUG && (current_debug_flags & flag) != 0;
}
void set_log_info_flags(uint32_t flags) { void set_log_info_flags(uint32_t flags) {
info_flags = flags; info_flags = flags;
info_flags_explicit = true; info_flags_explicit = true;
+4
View File
@@ -29,6 +29,10 @@ void log_perror(const char* context);
void set_log_level(LogLevel level); void set_log_level(LogLevel level);
void set_log_debug_flags(uint32_t flags); void set_log_debug_flags(uint32_t flags);
uint32_t get_log_debug_flags(void); uint32_t get_log_debug_flags(void);
/* True when a log_debug_message() call with the same flag would actually emit:
* the debug log level is enabled AND the flag is selected. Hot paths use this
* to skip expensive message formatting/escaping when the line is filtered. */
bool log_debug_enabled(LogDebugFlag flag);
void log_debug_message(LogDebugFlag flag, const char* message, ...); void log_debug_message(LogDebugFlag flag, const char* message, ...);
void set_log_info_flags(uint32_t flags); void set_log_info_flags(uint32_t flags);
uint32_t get_log_info_flags(void); uint32_t get_log_info_flags(void);
+2 -2
View File
@@ -441,7 +441,7 @@ static bool protocol_send_str_impl(ProtocolSession* session, const char* data, b
return false; return false;
if (redact) { if (redact) {
log_debug_message(LOG_DEBUG_PROTO, "Send String: <redacted>"); log_debug_message(LOG_DEBUG_PROTO, "Send String: <redacted>");
} else { } else if (log_debug_enabled(LOG_DEBUG_PROTO)) {
char* escaped_data = output_escape(data, log_get_8_bit_output()); char* escaped_data = output_escape(data, log_get_8_bit_output());
log_debug_message(LOG_DEBUG_PROTO, "Send String: %s", log_debug_message(LOG_DEBUG_PROTO, "Send String: %s",
escaped_data ? escaped_data : "<allocation failed>"); escaped_data ? escaped_data : "<allocation failed>");
@@ -474,7 +474,7 @@ static char* protocol_receive_str_impl(ProtocolSession* session, bool redact) {
data[size] = '\0'; data[size] = '\0';
if (redact) { if (redact) {
log_debug_message(LOG_DEBUG_PROTO, "Received String: <redacted>"); log_debug_message(LOG_DEBUG_PROTO, "Received String: <redacted>");
} else { } else if (log_debug_enabled(LOG_DEBUG_PROTO)) {
char* escaped_data = output_escape(data, log_get_8_bit_output()); char* escaped_data = output_escape(data, log_get_8_bit_output());
log_debug_message(LOG_DEBUG_PROTO, "Received String: %s", log_debug_message(LOG_DEBUG_PROTO, "Received String: %s",
escaped_data ? escaped_data : "<allocation failed>"); escaped_data ? escaped_data : "<allocation failed>");
+20
View File
@@ -128,6 +128,25 @@ static void test_log_message_formats() {
EXPECT_TRUE(true); EXPECT_TRUE(true);
} }
/* log_debug_enabled is the lazy-formatting gate for log_debug_message: it must
* be true only at DEBUG level with the requested flag selected, exactly
* mirroring the filter inside log_debug_message itself. */
static void test_log_debug_enabled_matches_gate() {
set_log_level(LOG_LEVEL_WARNING);
set_log_debug_flags(LOG_DEBUG_ALL);
EXPECT_FALSE(log_debug_enabled(LOG_DEBUG_PROTO));
set_log_level(LOG_LEVEL_DEBUG);
set_log_debug_flags(LOG_DEBUG_PROTO);
EXPECT_TRUE(log_debug_enabled(LOG_DEBUG_PROTO));
EXPECT_FALSE(log_debug_enabled(LOG_DEBUG_IO));
set_log_debug_flags(0);
EXPECT_FALSE(log_debug_enabled(LOG_DEBUG_PROTO));
set_log_debug_flags(LOG_DEBUG_ALL);
}
void test_log() { void test_log() {
test_log_message_debug(); test_log_message_debug();
test_log_message_info(); test_log_message_info();
@@ -139,4 +158,5 @@ void test_log() {
test_log_filtering(); test_log_filtering();
test_log_stderr_mode_all(); test_log_stderr_mode_all();
test_log_message_formats(); test_log_message_formats();
test_log_debug_enabled_matches_gate();
} }