GNU libmicrohttpd 1.0.9
Loading...
Searching...
No Matches
mhd_check.h File Reference

macros for MHD_CHECK_(), always-compiled memory-safety invariants More...

#include "mhd_options.h"
Include dependency graph for mhd_check.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MHD_CHECK_FAILED_(expr)
 
#define MHD_CHECK_LOG_(daemon, expr_str)
 
#define MHD_CHECK_(daemon, expr, fail_stmt)
 
#define MHD_CHECK_RET_(expr, retval)
 
#define MHD_CHECK_CONN_CLOSE_RET_(c, expr, retval)
 
#define MHD_CHECK_CONN_CLOSE_RET_VOID_(c, expr)
 
#define MHD_CHECK_CONN_REPLY_RET_(c, expr, code, msg, retval)
 

Detailed Description

macros for MHD_CHECK_(), always-compiled memory-safety invariants

Author
Christian Grothoff

mhd_assert() is compiled out in release builds (NDEBUG), which is the right thing for the several hundred internal state assertions of this library but the wrong thing for the handful of them that stand between attacker-supplied data and a memmove()/memcpy()/array index. For those, an assertion that is absent in the shipped build is not a safety net at all.

MHD_CHECK_() is the always-compiled companion for exactly that subset. It does NOT depend on NDEBUG, _DEBUG or –enable-asserts: the test is one predictable, well-predicted branch that is present in every build.

RULES FOR USING IT

  1. Only invariants whose violation would mean memory-unsafe behaviour - pointer/offset arithmetic, buffer bounds, length subtractions that could underflow, indices into fixed-size arrays. Ordinary state assertions stay mhd_assert().
  2. Check the precondition, not the symptom. An assertion that compares two pointers after the bad one has already been derived is decoration: it happily passes on a NULL-derived pointer. Assert what has to be true for the following arithmetic to be defined. See commit 29eaa56b.
  3. A failing check must FAIL THE CONNECTION - close it, or reply 4xx/5xx - and must not continue and must not panic. MHD_PANIC() aborts the whole daemon, which turns a bounded per-connection problem into a global denial of service; that is the opposite of what this is for.
  4. Deliberately no mhd_assert() inside: a check must behave identically in debug and in release builds, otherwise the debug build stops exercising the recovery path that the release build relies on.

WHERE THE MACROS COME FROM

The connection-level macros below expand to the failure exits that connection.c already uses - connection_close_error() / CONNECTION_CLOSE_ERROR() and transmit_error_response_static() - rather than introducing a parallel mechanism. They are therefore usable only from connection.c and only after those helpers have been defined; this header intentionally does not include connection.c's internals, the macros are expanded at the point of use.

Translation units that have a struct MHD_Daemon * at hand (connection.c, digestauth.c, postprocessor.c, ...) get a log line through the usual MHD_DLOG()/HAVE_MESSAGES machinery; they must include "internal.h" before this header. Translation units without a daemon (memorypool.c, mhd_str.c) use the MHD_CHECK_RET_() form, which is silent.

Definition in file mhd_check.h.

Macro Definition Documentation

◆ MHD_CHECK_

#define MHD_CHECK_ ( daemon,
expr,
fail_stmt )
Value:
do { \
if (MHD_CHECK_FAILED_ (expr)) \
{ \
MHD_CHECK_LOG_ (daemon, #expr); \
fail_stmt; \
} \
} while (0)
#define MHD_CHECK_FAILED_(expr)
Definition mhd_check.h:81

The generic always-compiled invariant check.

Parameters
daemonthe daemon to log to
exprthe invariant, must evaluate to true
fail_stmta single statement to execute when expr is false; it must transfer control out of the current function (return, goto or break), because execution must not continue past a violated memory-safety invariant. When the failure action needs several statements, spell the check out instead - "if (MHD_CHECK_FAILED_ (expr)) { MHD_CHECK_LOG_ (daemon, "expr"); ... }" - because a braced block passed as a macro argument is re-indented by contrib/uncrustify.cfg

Definition at line 118 of file mhd_check.h.

Referenced by digest_auth_check_all_inner().

◆ MHD_CHECK_CONN_CLOSE_RET_

#define MHD_CHECK_CONN_CLOSE_RET_ ( c,
expr,
retval )
Value:
MHD_CHECK_ ((c)->daemon, \
expr, \
{ \
connection_close_error ((c), \
NULL); \
return retval; \
})
#define MHD_CHECK_(daemon, expr, fail_stmt)
Definition mhd_check.h:118
#define NULL

Always-compiled invariant check that closes the connection with an error and returns retval. For use in connection.c only, and only after connection_close_error() has been defined.

Parameters
cthe connection to fail
exprthe invariant, must evaluate to true
retvalthe value to return when expr is false

Definition at line 153 of file mhd_check.h.

Referenced by get_req_headers().

◆ MHD_CHECK_CONN_CLOSE_RET_VOID_

#define MHD_CHECK_CONN_CLOSE_RET_VOID_ ( c,
expr )
Value:
MHD_CHECK_ ((c)->daemon, \
expr, \
{ \
connection_close_error ((c), \
NULL); \
return; \
})

Always-compiled invariant check that closes the connection with an error and returns from a void function. For use in connection.c only, and only after connection_close_error() has been defined.

Parameters
cthe connection to fail
exprthe invariant, must evaluate to true

Definition at line 171 of file mhd_check.h.

◆ MHD_CHECK_CONN_REPLY_RET_

#define MHD_CHECK_CONN_REPLY_RET_ ( c,
expr,
code,
msg,
retval )
Value:
MHD_CHECK_ ((c)->daemon, \
expr, \
{ \
transmit_error_response_static ((c), \
(code), \
msg); \
return retval; \
})

Always-compiled invariant check that queues a static error reply for the connection and returns retval. For use in connection.c only, and only after transmit_error_response_static() has been defined.

Parameters
cthe connection to fail
exprthe invariant, must evaluate to true
codethe HTTP status code to reply with
msgthe static message to reply with
retvalthe value to return when expr is false

Definition at line 192 of file mhd_check.h.

◆ MHD_CHECK_FAILED_

#define MHD_CHECK_FAILED_ ( expr)
Value:
(! (expr))

Branch hint: an invariant violation is by construction the unlikely case.

Definition at line 81 of file mhd_check.h.

Referenced by send_redirect_fixed_rq_target(), and try_ready_chunked_body().

◆ MHD_CHECK_LOG_

#define MHD_CHECK_LOG_ ( daemon,
expr_str )
Value:
((void) 0)

Report a violated invariant through the daemon's log.

Parameters
daemonthe daemon to log to
expr_strthe stringified invariant that was violated

Definition at line 99 of file mhd_check.h.

Referenced by send_redirect_fixed_rq_target(), and try_ready_chunked_body().

◆ MHD_CHECK_RET_

#define MHD_CHECK_RET_ ( expr,
retval )
Value:
do { \
if (MHD_CHECK_FAILED_ (expr)) \
return retval; \
} while (0)

Always-compiled invariant check for translation units that have no daemon pointer available for logging (memorypool.c, mhd_str.c). Silent; the caller is expected to turn the returned failure value into a log message and a failed connection.

Parameters
exprthe invariant, must evaluate to true
retvalthe value to return when expr is false

Definition at line 137 of file mhd_check.h.

Referenced by MHD_pool_reallocate().