Skip to content

Commit c81bc16

Browse files
committed
fix: avoid longjmp crash on ARM64/macOS when connection is aborted
php_handle_aborted_connection() calls zend_bailout() which does a longjmp(). On ARM64/macOS with Pointer Authentication (PAC), the jmp_buf signature check fails because the buffer was signed in a different stack frame, causing a SIGBUS crash. Inline the effect of php_handle_aborted_connection() without calling zend_bailout(): set PG(connection_status) = PHP_CONNECTION_ABORTED and php_output_set_status(PHP_OUTPUT_DISABLED). PHP detects the abort at safe points (between opcodes via zend_interrupt checks) instead of longjmping out of the SAPI write handler. This matches the approach used by Nginx Unit's PHP SAPI: https://github.com/nginx/unit/blob/master/src/nxt_php_sapi.c#L271 Affects both frankenphp_ub_write and frankenphp_sapi_flush.
1 parent c12841b commit c81bc16

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

frankenphp.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,18 @@ static size_t frankenphp_ub_write(const char *str, size_t str_length) {
743743
go_ub_write(thread_index, (char *)str, str_length);
744744

745745
if (result.r1) {
746-
php_handle_aborted_connection();
746+
/*
747+
* Inline the effect of php_handle_aborted_connection() without calling
748+
* zend_bailout(). On ARM64/macOS, zend_bailout() triggers longjmp()
749+
* which crashes due to PAC (Pointer Authentication) verification failure
750+
* on the jmp_buf — the buffer was signed in a different stack frame.
751+
*
752+
* This matches Nginx Unit's approach (nxt_php_sapi.c): set the
753+
* connection status and disable output, letting PHP detect the abort
754+
* at safe points (e.g. between opcodes via zend_interrupt checks).
755+
*/
756+
PG(connection_status) = PHP_CONNECTION_ABORTED;
757+
php_output_set_status(PHP_OUTPUT_DISABLED);
747758
}
748759

749760
return result.r0;
@@ -777,7 +788,8 @@ static int frankenphp_send_headers(sapi_headers_struct *sapi_headers) {
777788
static void frankenphp_sapi_flush(void *server_context) {
778789
sapi_send_headers();
779790
if (go_sapi_flush(thread_index)) {
780-
php_handle_aborted_connection();
791+
PG(connection_status) = PHP_CONNECTION_ABORTED;
792+
php_output_set_status(PHP_OUTPUT_DISABLED);
781793
}
782794
}
783795

0 commit comments

Comments
 (0)