fix(protocol): harden STATUS_ERROR_DETAIL receive path
Address review/security findings in the 2.21.0 error-detail feature: - Keepalive drain no longer erases the terminal detail: capture/clear is skipped for STATUS_KEEPALIVE so the reason the peer just sent survives the owed keepalive replies. - Replace the capture path with a dedicated protocol_receive_error_detail: the declared length is validated against MAX_ERROR_DETAIL_BYTES before any allocation, over-cap bodies are drained through a fixed scratch buffer (so the stream never desyncs), in-cap bodies read straight into the thread-local detail buffer, and session->max_alloc is never raised. Lengths beyond MAX_STRING_SIZE are treated as a fatal framing error. - The detail body now honors the caller's deadline (timed/keepalive paths) and polls the abort callback between drain chunks. - Escape peer-controlled detail text with output_escape before logging it in client_send.c and config.c. - Clear io_error_detail in io_set_fds so a new connection on the same thread cannot inherit a stale reason. - Add unit tests for the keepalive-survival, over-cap drain, absurd-length fatal framing, and deadline-clamped body read cases.
This commit is contained in:
@@ -212,8 +212,11 @@ bool receive_status(int file_descriptor, Status* status);
|
||||
bool send_error_detail(int file_descriptor, const char* message);
|
||||
/* Human-readable reason captured from the most recent STATUS_ERROR_DETAIL
|
||||
* received on this thread, or "" when the last status was a bare STATUS_ERROR
|
||||
* (or no detail was seen). Thread-local, and valid until the next status read
|
||||
* on the same thread. */
|
||||
* (or no detail was seen). Thread-local, and valid until the next non-keepalive
|
||||
* status read on the same thread; a later STATUS_KEEPALIVE does NOT clear it.
|
||||
* The detail body is bounded by MAX_ERROR_DETAIL_BYTES: an over-cap declared
|
||||
* length is drained and yields "" (so the stream never desyncs), while an
|
||||
* absurd length is a fatal framing error that fails the status read. */
|
||||
const char* protocol_last_error(void);
|
||||
/* Clear the thread-local last-error buffer. */
|
||||
void protocol_clear_last_error(void);
|
||||
|
||||
Reference in New Issue
Block a user