Bug #81580 [Opn]: SEGV (probably stack limits) while autoloading from a shutdown function

From: Date: Thu, 04 Nov 2021 14:46:20 +0000
Subject: Bug #81580 [Opn]: SEGV (probably stack limits) while autoloading from a shutdown function
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-237557@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=81580&edit=1

 ID:                 81580
 User updated by:    patrick dot schaaf at yalwa dot com
 Reported by:        patrick dot schaaf at yalwa dot com
 Summary:            SEGV (probably stack limits) while autoloading from
                     a shutdown function
 Status:             Open
 Type:               Bug
 Package:            Reproducible crash
 Operating System:   openSUSE Tumbleweed
 PHP Version:        8.0.12
 Block user comment: N
 Private report:     N

 New Comment:

Thanks for your reply, Niki.

This can't be something generally bad about our detect_bot class source / file, as we are
really using that sprintf+detect_bot sequence for almost all web requests of our production
codebase, and that has been active with php 8 (8.0.9, mostly, but now also 8.0.12) on several dozen
web developer VMs, as well as a few internal web tools servers used every day by employees.

That specific coredump with that backtrace, only triggered on our public facing imageserver, and
there, quite quickly and repeatedly. So I fear this will be some corruption elsewhere
cross-interfering.

Regardless, given your hint that a long sequence of concatenations can lead to that backtrace, I can
confirm that we indeed DO have something like that in the file, during define() of a few constants
(building up large many-alternative regexpen). Quite needlessly so, just for readability, maybe I
should reconsider that... The larger of these, actually concatenates 728 times, which times three,
almost gives the depth of that backtrace.

So call me silly for that. Nevertheless, would you have any idea on how to debug this further
regarding the actual SEGV seen there, or a suspicion I could followup on to try to make it
reproducible?


Previous Comments:
------------------------------------------------------------------------
[2021-11-04 14:32:45] nikic@php.net

If this is due to memory corruption, then running apache under valgrind (using USE_ZEND_ALLOC=0
valgrind httpd -X I believe) may show where it originates (possibly also reliably without requiring
multiple requests).

------------------------------------------------------------------------
[2021-11-04 14:22:01] nikic@php.net

Not sure this is a stack overflow, the crash location is pretty typical for memory corruption.
Deeply nested zend_compile_binary_op() can occur for code containing a very large "a" .
"b" . "c" style expression with many operands. Is something like that present in
the detect_bot file?

------------------------------------------------------------------------
[2021-11-01 06:49:49] patrick dot schaaf at yalwa dot com

Description:
------------
Unfortunately, reproducible, but only in the sense of running production traffic and waiting a few
hundred requests for the first coredump... I encounter SEGVs quickly on our production codebase,
which has been running stably on the late(st) PHP 5.6 (yeah...), in our attempts at finally making
the jump to PHP 8.

System / context is openSUSE tumbleweed, pretty much latest, current apache, mod_php8 at PHP level
8.0.12. opcache disabled (not installed at all) because we saw other issues with opcache that
I'll try to reoirt seoarateky.

Code context: We have a little homegrown autoloader in use there, and also pretty much each web
request, registers shutdown function; one of them, was consistently implicated in 4 coredumps I got
in quick succession (seconds apart) on trying 8.0.12 with our production load. Actual place there in
the shutdown function, seen by a bit of gdb backtrace + data inspection, is a call to sprintf() with
one of the parameters, being a class_name::method() static call for a class in all these four cases
not yet autoloaded - triggering the autoloader for it and then that goes into a three-function stack
eating recursive triangle of calls for a few thousand frames while walking the AST.

Emphasis on this is something we do on each request served there, same on a ton of development
systems where we never saw the crashes / coredumps, weirdly. Trying to reproduce with same context
(shutdown function running while that class was not autoloaded), I could not reproduce it "just
so" either, unfortunately.

Test script:
---------------
Don't have a reliable reproding test script, sorry. Here is what the call in the shutdown
function actually looks like, abbreviated:

apache_note('phpstat',
sprintf("%s-%s:%.0f:%.0f-%.0f:%.0f-%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%.0f:%s:%s:%s:%s:%s",
  self::$page,
...
  # <-- crashes while autoloading / compiling "detect_bot" from here
  detect_bot::get_apache_logtag(),
...
));

Actual result:
--------------
gdb / backtrace info, if anything is missing that you need to know, tell me the frame # and what to
look for.

----------------------
Core was generated by `/usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -DSTATUS -C PidFile /run/httpd.pid
-C'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  zend_mm_alloc_small (bin_num=24, heap=0x7f31a4e00040) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_alloc.c:1255
1255                    heap->free_slot[bin_num] = p->next_free_slot;
----------------------
(gdb) bt
#0  zend_mm_alloc_small (bin_num=24, heap=0x7f31a4e00040) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_alloc.c:1255
#1  zend_mm_alloc_heap (size=<optimized out>, heap=0x7f31a4e00040) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_alloc.c:1326
#2  _emalloc (size=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_alloc.c:2540
#3  0x00007f31a57dcc32 in zend_string_alloc (persistent=false, len=1003) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_string.h:143
#4  concat_function (result=0x7ffe8caef5c8, op1=<optimized out>, op2=<optimized out>)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_operators.c:1899
#5  0x00007f31a57c9e36 in zend_try_ct_eval_binary_op (op2=0x7ffe8caef4f8, op1=0x7ffe8caef4d8,
opcode=8, result=0x7ffe8caef5c8)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:7918
#6  zend_try_ct_eval_binary_op (op2=0x7ffe8caef4f8, op1=0x7ffe8caef4d8, opcode=8,
result=0x7ffe8caef5c8)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:7911
#7  zend_compile_binary_op (ast=0x7ffe8caef4f8, result=0x7ffe8caef5c0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:8094
#8  zend_compile_expr_inner (result=0x7ffe8caef5c0, ast=0x7ffe8caef4f8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9538
#9  0x00007f31a57ca26c in zend_compile_expr (result=0x7ffe8caef5c0, ast=0x7f31a4f18cc8)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9640
#10 0x00007f31a57c8506 in zend_compile_binary_op (ast=0x7f31a4f18cf8, result=0x7ffe8caef6b0)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:8090
#11 zend_compile_expr_inner (result=0x7ffe8caef6b0, ast=0x7f31a4f18cf8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9538
#12 0x00007f31a57ca26c in zend_compile_expr (result=0x7ffe8caef6b0, ast=0x7f31a4f18cf8)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9640
#13 0x00007f31a57c8506 in zend_compile_binary_op (ast=0x7f31a4f18d28, result=0x7ffe8caef7a0)
    at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:8090

*** THESE THREE FRAMES, LIKE #11/#12/#13, then repeat over and over for a long stretch ***

#1830 0x00007f31a57ca26c in zend_compile_expr (result=0x7ffe8cb12ed0, ast=0x7f31a4f24ec0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9640
#1831 0x00007f31a57c8506 in zend_compile_binary_op (ast=0x7f31a4f24ef0, result=0x7ffe8cb12fc0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:8090
#1832 zend_compile_expr_inner (result=0x7ffe8cb12fc0, ast=0x7f31a4f24ef0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9538
#1833 0x00007f31a57ba04d in zend_compile_expr (ast=0x7f31a4f24ef0, result=0x7ffe8cb12fc0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9640
#1834 zend_compile_args (may_have_extra_named_args=<synthetic pointer>, fbc=0x5562fea7d800,
ast=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:3481
#1835 zend_compile_call_common (result=<optimized out>, args_ast=<optimized out>,
fbc=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:3568
#1836 0x00007f31a57cadb8 in zend_compile_call (ast=0x7f31a4f24f08, ast=0x7f31a4f24f08,
type=<optimized out>, result=0x7ffe8cb131d0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:4355
#1837 zend_compile_var_inner (by_ref=<optimized out>, type=<optimized out>,
ast=0x7f31a4f24f08, result=0x7ffe8cb131d0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9659
#1838 zend_compile_var (result=0x7ffe8cb131d0, ast=0x7f31a4f24f08, type=<optimized out>,
by_ref=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9685
#1839 0x00007f31a57bfe77 in zend_compile_expr (ast=0x7f31a4f24f08, result=0x7ffe8cb131d0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9640
#1840 zend_compile_stmt (ast=0x7f31a4f24f08) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9482
#1841 0x00007f31a57bfb7f in zend_compile_stmt_list (ast=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:5990
#1842 zend_compile_stmt (ast=0x7f31a4f16cb8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9394
#1843 0x00007f31a57c4a6c in zend_compile_func_decl (result=<optimized out>, ast=<optimized
out>, toplevel=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:6988
#1844 0x00007f31a57c015c in zend_compile_stmt (ast=0x7f31a4f24f20) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9447
#1845 0x00007f31a57bfb7f in zend_compile_stmt_list (ast=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:5990
#1846 zend_compile_stmt (ast=0x7f31a4f2fef8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9394
#1847 0x00007f31a57c587a in zend_compile_class_decl (result=0x0, ast=0x7f31a4f30510,
toplevel=<optimized out>) at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86
64/Zend/zend_compile.c:7398
#1848 0x00007f31a57c652d in zend_compile_top_stmt (ast=0x7f31a4f30510) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9369
#1849 zend_compile_top_stmt (ast=0x7f31a4efe018) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_compile.c:9358
#1850 0x00007f31a579fd16 in zend_compile (type=type@entry=2) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_language_scanner.c:630
#1851 0x00007f31a57a015a in compile_file (file_handle=0x7ffe8cb13d20, type=8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_language_scanner.c:665
#1852 0x00007f31a279bf2a in phar_compile_file (file_handle=0x7ffe8cb13d20, type=8) at
/usr/src/debug/php8-8.0.12-1.1.x86_64/ext/phar/phar.c:3364
#1853 0x00007f31a57a01d3 in compile_filename (type=8, filename=0x7f31a4e11fe0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_language_scanner.c:721
#1854 0x00007f31a57fe277 in zend_include_or_eval (inc_filename=0x7f31a4e11fe0, type=8) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute.c:4274
#1855 0x00007f31a580f914 in ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER (execute_data=0x7f31a4e11f10)
at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_vm_execute.h:14266
#1856 0x00007f31a584d1d8 in execute_ex (ex=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_vm_execute.h:53978
#1857 0x00007f31a57d008e in zend_call_function (fci=<optimized out>, fci_cache=<optimized
out>) at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:895
#1858 0x00007f31a57d044a in zend_call_known_function (fn=0x7f31a4e013d8, object=<optimized
out>, called_scope=<optimized out>, retval_ptr=<optimized out>,
param_count=<optimized out>, params=0x7ffe8cb140d0, named_params=0x0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:985
#1859 0x00007f31a56d5c4f in spl_perform_autoload (class_name=0x7f31a4e8f870, lc_name=0x7f31a4e8f870)
at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/ext/spl/php_spl.c:440
#1860 0x00007f31a57cf5b0 in zend_lookup_class_ex (name=name@entry=0x7f31a4e8f870,
key=0x7f31a4e8f870, flags=flags@entry=512) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:1110
#1861 0x00007f31a57d49ef in zend_fetch_class_by_name (class_name=0x7f31a4e8f870, key=<optimized
out>, fetch_type=512) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:1521
#1862 0x00007f31a5807d48 in ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER
(execute_data=0x7f31a4e11020) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_vm_execute.h:6570
#1863 0x00007f31a584d1d8 in execute_ex (ex=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_vm_execute.h:53978
#1864 0x00007f31a57d008e in zend_call_function (fci=<optimized out>, fci_cache=<optimized
out>) at /usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:895
#1865 0x00007f31a57ce4ce in _call_user_function_impl (object=<optimized out>,
function_name=<optimized out>, retval_ptr=<optimized out>, param_count=<optimized
out>, params=<optimized out>, named_params=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_execute_API.c:659
#1866 0x00007f31a570f224 in user_shutdown_function_call (zv=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/ext/standard/basic_functions.c:1693
#1867 0x00007f31a57ec7b2 in zend_hash_apply (ht=0x7f31a4e58700, apply_func=0x7f31a570f1e0
<user_shutdown_function_call>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/Zend/zend_hash.c:1837
#1868 0x00007f31a570f3d6 in php_call_shutdown_functions () at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/ext/standard/basic_functions.c:1766
#1869 0x00007f31a5776755 in php_request_shutdown (dummy=<optimized out>) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/main/main.c:1782
#1870 0x00007f31a587694f in php_apache_request_dtor (r=0x5562fed463c0) at
/usr/src/debug/apache2-mod_php8-8.0.12-1.1.x86_64/sapi/apache2handler/sapi_apache2.c:54


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=81580&edit=1


Thread (7 messages)

« previous php.bugs (#237557) next »