easysoft / phpmicro

micro sfx SAPI for php
Apache License 2.0
255 stars 30 forks source link

某些情况构建的 micro.sfx 容易出现 zend_mm_heap corrupted #11

Closed crazywhalecc closed 5 months ago

crazywhalecc commented 1 year ago

使用构建环境是 macOS Ventura arm64,构建命令:

./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes CFLAGS='--target=arm64-apple-darwin -Werror=unknown-warning-option' --disable-all --disable-cgi --disable-phpdbg --enable-cli --enable-fpm --enable-micro  --enable-bcmath --with-bz2="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-calendar --enable-ctype --with-curl --enable-dom --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-exif --enable-fileinfo --enable-filter --enable-ftp --with-zlib --enable-gd --with-gmp="/Users/jerry/project/git-project/static-php-cli/buildroot" --with-iconv="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-xml --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-mbstring --enable-mbregex --enable-mysqlnd --with-openssl --enable-pcntl --enable-pdo --with-pdo-mysql --with-sqlite3="/Users/jerry/project/git-project/static-php-cli/buildroot" --with-pdo-sqlite --enable-phar --enable-posix --enable-redis --disable-redis-session --enable-session --enable-simplexml --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-soap --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-sockets --enable-tokenizer --enable-xmlwriter --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --enable-xmlreader --with-libxml="/Users/jerry/project/git-project/static-php-cli/buildroot" --with-zip="/Users/jerry/project/git-project/static-php-cli/buildroot" PKG_CONFIG_PATH="/Users/jerry/project/git-project/static-php-cli/buildroot/lib/pkgconfig/" CC='clang' CXX='clang++' CFLAGS='--target=arm64-apple-darwin -Wimplicit-function-declaration'

make -j8 EXTRA_CFLAGS="-g -Os -fno-ident" EXTRA_LIBS="-framework CoreFoundation -framework SystemConfiguration /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libzip.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libsqlite3.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libonig.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libgmp.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libpng16.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libxml2.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libiconv.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libcharset.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libcurl.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libssl.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libcrypto.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libz.a /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libbz2.a -liconv -lresolv" STRIP="dsymutil -f " micro

加入了这么多扩展后,就会出现 zend_mm_heap corrupted,只使用少数几个扩展 mbstring,pcntl,posix,tokenizer 时就不会出现。

./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes CFLAGS='--target=arm64-apple-darwin -Werror=unknown-warning-option' --disable-all --disable-cgi --disable-phpdbg --enable-cli --enable-fpm --enable-micro  --enable-mbstring --disable-mbregex --enable-pcntl --enable-posix --enable-tokenizer PKG_CONFIG_PATH="/Users/jerry/project/git-project/static-php-cli/buildroot/lib/pkgconfig/" CC='clang' CXX='clang++' CFLAGS='--target=arm64-apple-darwin -Wimplicit-function-declaration'

 make -j8 EXTRA_CFLAGS="-g -Os -fno-ident" EXTRA_LIBS=" /Users/jerry/project/git-project/static-php-cli/buildroot/lib/libonig.a -lresolv" STRIP="dsymutil -f " micro

具体原因可能需要根据不同扩展之间是否有相互干扰的情况来处理了。这个是我尝试使用 static-php-cli 自身构建自身后的一个 phar。

static-php-cli.phar.zip

目前这个问题感觉不是个例,因为使用 Webman 的项目打包 phar 运行 micro 时也会出现这样的报错,社区也有很多反馈:

目前我猜想调试的方案只能一个一个扩展进行尝试了,但我之前也遇到过一些奇怪的问题,比如 Segment Fault,在 PHP 编译加上 --host= 参数并且优化选项采用 -Os 时,运行 phar 打包命令 $phar->buildFronDirectory() 就会导致段错误。具体成因不太清楚,gdb 调试也没调出什么有效信息,最顶栈基本就是随机跳到一个地方导致崩溃。

dixyes commented 1 year ago

才看到。。。 micro几乎没有动zend内存池的东西,目测是php本身的bug,或者micro的生命周期有些问题 我也没找到最小可复现demo

至于-Os的segv多半是编译器bug,如果能制作最小demo(c代码),可以向gcc/clang反馈问题

对于micro的调试 可以把debug打开,strip关掉,打开asan(我一般直接改makefile),然后有符号的情况下进行调试,Linux上比较方便,mac/windows比较痛苦(mac缺少调试工具,还有些莫名其妙的完整性检查策略,windows下debug构建比较麻烦)

avriltank commented 5 months ago

最小复现demo,参见这个issue(https://github.com/crazywhalecc/static-php-cli/issues/460)

<?php
define("K_SP"," ");
define("K_exclam","!");
define("K_quotedbl","\"");
define("K_numbersign","#");
define("K_dollar","$");
define("K_percent","%");
define("K_ampersand","&");
define("K_apostrophe","'");
define("K_parentleft","(");
define("K_parentright",")");
define("K_asterisk","*");
define("K_plus","+");
define("K_comma",",");
define("K_minus","-");
define("K_period",".");
define("K_slash","/");
define("K_0","0");
define("K_1","1");
define("K_2","2");
define("K_3","3");
define("K_4","4");
define("K_5","5");
define("K_6","6");
define("K_7","7");
define("K_8","8");
define("K_9","9");
define("K_colon",":");
define("K_semicolon",";");
define("K_less","<");
define("K_equal","=");
define("K_greater",">");
define("K_question","?");
define("K_at","@");
define("K_A","A");
define("K_B","B");
define("K_C","C");
define("K_D","D");
define("K_E","E");
define("K_F","F");
define("K_G","G");
define("K_H","H");
define("K_I","I");
define("K_J","J");
define("K_K","K");
define("K_L","L");
define("K_M","M");
define("K_N","N");
define("K_O","O");
define("K_P","P");
define("K_Q","Q");
define("K_R","R");
define("K_S","S");
define("K_T","T");
define("K_U","U");
define("K_V","V");
define("K_W","W");
define("K_X","X");
define("K_Y","Y");
define("K_Z","Z");
define("K_bracketleft","[");
define("K_bracketright","]");
define("K_circum","^");
define("K_underscore","_");
define("K_grave","`");
define("K_a","a");
define("K_b","b");
define("K_c","c");
define("K_d","d");
define("K_e","e");
define("K_f","f");
define("K_g","g");
define("K_h","h");
define("K_i","i");
define("K_j","j");
define("K_k","k");
define("K_l","l");
define("K_m","m");
define("K_n","n");
define("K_o","o");
define("K_p","p");
define("K_q","q");
define("K_r","r");
define("K_s","s");
define("K_t","t");
define("K_u","u");
define("K_v","v");
define("K_w","w");
define("K_x","x");
define("K_y","y");
define("K_z","z");
define("K_braceleft","{");
define("K_bar","|");
define("K_braceright","}");
define("K_tilde","~");
define("K_BS","\b");
define("K_TAB","\t");
define("K_LF","\n");
define("K_CR","\r");
define("K_quoteleft","`");
define("K_quoteright","'");
define("K_PAUSE",65299);
define("K_ESC",65307);
define("K_HOME",65360);
define("K_LEFT",65361);
define("K_UP",65362);
define("K_RIGHT",65363);
define("K_DOWN",65364);
define("K_PGUP",65365);
define("K_PGDN",65366);
define("K_END",65367);
define("K_MIDDLE",65291);
define("K_Print",65377);
define("K_INS",65379);
define("K_Menu",65383);
define("K_DEL",65535);
define("K_F1",65470);
define("K_F2",65471);
define("K_F3",65472);
define("K_F4",65473);
define("K_F5",65474);
define("K_F6",65475);
define("K_F7",65476);
define("K_F8",65477);
define("K_F9",65478);
define("K_F10",65479);
define("K_F11",65480);
define("K_F12",65481);
define("K_F13",65482);
define("K_F14",65483);
define("K_F15",65484);
define("K_F16",65485);
define("K_F17",65486);
define("K_F18",65487);
define("K_F19",65488);
define("K_F20",65489);
define("K_LSHIFT",65505);
define("K_RSHIFT",65506);
define("K_LCTRL",65507);
define("K_RCTRL",65508);
define("K_LALT",65513);
define("K_RALT",65514);
define("K_NUM",65407);
define("K_SCROLL",65300);
define("K_CAPS",65509);
define("K_CLEAR",65490);
define("K_HELP",65491);
define("K_ccedilla",231);
define("K_Ccedilla",199);
define("K_acute",180);
define("K_diaeresis",168);
define("IUP_RUN","RUN");
define("IUP_ENGLISH","ENGLISH");
define("IUP_PORTUGUESE","PORTUGUESE");
define("IUP_SBH","SBH");
define("IUP_SBV","SBV");
define("IUP_IDLE_ACTION","IDLE_ACTION");
define("IUP_ACTION","ACTION");
define("IUP_GETFOCUS_CB","GETFOCUS_CB");
define("IUP_KILLFOCUS_CB","KILLFOCUS_CB");
define("IUP_K_ANY","K_ANY");
define("IUP_KEYPRESS_CB","KEYPRESS_CB");
define("IUP_HELP_CB","HELP_CB");
define("IUP_SCROLL_CB","SCROLL_CB");
define("IUP_RESIZE_CB","RESIZE_CB");
define("IUP_MOTION_CB","MOTION_CB");
define("IUP_BUTTON_CB","BUTTON_CB");
define("IUP_ENTERWINDOW_CB","ENTERWINDOW_CB");
define("IUP_LEAVEWINDOW_CB","LEAVEWINDOW_CB");
define("IUP_WHEEL_CB","WHEEL_CB");
define("IUP_MASK_CB","MASK_CB");
define("IUP_OPEN_CB","OPEN_CB");
define("IUP_HIGHLIGHT_CB","HIGHLIGHT_CB");
define("IUP_MENUCLOSE_CB","MENUCLOSE_CB");
define("IUP_MAP_CB","MAP_CB");
define("IUP_CLOSE_CB","CLOSE_CB");
define("IUP_SHOW_CB","SHOW_CB");
define("IUP_DROPFILES_CB","DROPFILES_CB");
define("IUP_WOM_CB","WOM_CB");
define("IUP_DIRECTION","DIRECTION");
define("IUP_ACTIVE","ACTIVE");
define("IUP_BGCOLOR","BGCOLOR");
define("IUP_FRAMECOLOR","FRAMECOLOR");
define("IUP_FGCOLOR","FGCOLOR");
define("IUP_COLOR","COLOR");
define("IUP_WID","WID");
define("IUP_SIZE","SIZE");
define("IUP_RASTERSIZE","RASTERSIZE");
define("IUP_TITLE","TITLE");
define("IUP_VALUE","VALUE");
define("IUP_VISIBLE","VISIBLE");
define("IUP_FONT","FONT");
define("IUP_TIP","TIP");
define("IUP_EXPAND","EXPAND");
define("IUP_SEPARATOR","SEPARATOR");
define("IUP_HOTSPOT","HOTSPOT");
define("IUP_HEIGHT","HEIGHT");
define("IUP_WIDTH","WIDTH");
define("IUP_KEY","KEY");
define("IUP_MULTIPLE","MULTIPLE");
define("IUP_DROPDOWN","DROPDOWN");
define("IUP_VISIBLE_ITEMS","VISIBLE_ITEMS");
define("IUP_MARGIN","MARGIN");
define("IUP_GAP","GAP");
define("IUP_ALIGNMENT","ALIGNMENT");
define("IUP_IMAGE","IMAGE");
define("IUP_IMINACTIVE","IMINACTIVE");
define("IUP_IMPRESS","IMPRESS");
define("IUP_WIN_SAVEBITS","WIN_SAVEBITS");
define("IUP_NC","NC");
define("IUP_MASK","MASK");
define("IUP_APPEND","APPEND");
define("IUP_BORDER","BORDER");
define("IUP_CARET","CARET");
define("IUP_SELECTION","SELECTION");
define("IUP_SELECTEDTEXT","SELECTEDTEXT");
define("IUP_INSERT","INSERT");
define("IUP_CONID","CONID");
define("IUP_CURSOR","CURSOR");
define("IUP_ICON","ICON");
define("IUP_MENUBOX","MENUBOX");
define("IUP_MINBOX","MINBOX");
define("IUP_MAXBOX","MAXBOX");
define("IUP_RESIZE","RESIZE");
define("IUP_MENU","MENU");
define("IUP_STARTFOCUS","STARTFOCUS");
define("IUP_PARENTDIALOG","PARENTDIALOG");
define("IUP_SHRINK","SHRINK");
define("IUP_DEFAULTENTER","DEFAULTENTER");
define("IUP_DEFAULTESC","DEFAULTESC");
define("IUP_X","X");
define("IUP_Y","Y");
define("IUP_TOOLBOX","TOOLBOX");
define("IUP_CONTROL","CONTROL");
define("IUP_READONLY","READONLY");
define("IUP_SCROLLBAR","SCROLLBAR");
define("IUP_POSY","POSY");
define("IUP_POSX","POSX");
define("IUP_DX","DX");
define("IUP_DY","DY");
define("IUP_XMAX","XMAX");
define("IUP_XMIN","XMIN");
define("IUP_YMAX","YMAX");
define("IUP_YMIN","YMIN");
define("IUP_RED","255 0 0");
define("IUP_GREEN","0 255 0");
define("IUP_BLUE","0 0 255");
define("IUP_MIN","MIN");
define("IUP_MAX","MAX");
define("IUP_TIME","TIME");
define("IUP_DRAG","DRAG");
define("IUP_DROP","DROP");
define("IUP_REPAINT","REPAINT");
define("IUP_TOPMOST","TOPMOST");
define("IUP_CLIPCHILDREN","CLIPCHILDREN");
define("IUP_DIALOGTYPE","DIALOGTYPE");
define("IUP_FILE","FILE");
define("IUP_MULTIPLEFILES","MULTIPLEFILES");
define("IUP_FILTER","FILTER");
define("IUP_FILTERUSED","FILTERUSED");
define("IUP_FILTERINFO","FILTERINFO");
define("IUP_EXTFILTER","EXTFILTER");
define("IUP_DIRECTORY","DIRECTORY");
define("IUP_ALLOWNEW","ALLOWNEW");
define("IUP_NOOVERWRITEPROMPT","NOOVERWRITEPROMPT");
define("IUP_NOCHANGEDIR","NOCHANGEDIR");
define("IUP_FILEEXIST","FILEEXIST");
define("IUP_STATUS","STATUS");
define("IUP_LOCKLOOP","LOCKLOOP");
define("IUP_SYSTEM","SYSTEM");
define("IUP_DRIVER","DRIVER");
define("IUP_SCREENSIZE","SCREENSIZE");
define("IUP_SYSTEMLANGUAGE","SYSTEMLANGUAGE");
define("IUP_COMPUTERNAME","COMPUTERNAME");
define("IUP_USERNAME","USERNAME");
define("IUP_OPEN","OPEN");
define("IUP_SAVE","SAVE");
define("IUP_DIR","DIR");
define("IUP_HORIZONTAL","HORIZONTAL");
define("IUP_VERTICAL","VERTICAL");
define("IUP_YES","YES");
define("IUP_NO","NO");
define("IUP_ON","ON");
define("IUP_OFF","OFF");
define("IUP_ACENTER","ACENTER");
define("IUP_ALEFT","ALEFT");
define("IUP_ARIGHT","ARIGHT");
define("IUP_ATOP","ATOP");
define("IUP_ABOTTOM","ABOTTOM");
define("IUP_NORTH","NORTH");
define("IUP_SOUTH","SOUTH");
define("IUP_WEST","WEST");
define("IUP_EAST","EAST");
define("IUP_NE","NE");
define("IUP_SE","SE");
define("IUP_NW","NW");
define("IUP_SW","SW");
define("IUP_FULLSCREEN","FULLSCREEN");
define("IUP_FULL","FULL");
define("IUP_HALF","HALF");
define("IUP_THIRD","THIRD");
define("IUP_QUARTER","QUARTER");
define("IUP_EIGHTH","EIGHTH");
define("IUP_ARROW","ARROW");
define("IUP_BUSY","BUSY");
define("IUP_RESIZE_N","RESIZE_N");
define("IUP_RESIZE_S","RESIZE_S");
define("IUP_RESIZE_E","RESIZE_E");
define("IUP_RESIZE_W","RESIZE_W");
define("IUP_RESIZE_NE","RESIZE_NE");
define("IUP_RESIZE_NW","RESIZE_NW");
define("IUP_RESIZE_SE","RESIZE_SE");
define("IUP_RESIZE_SW","RESIZE_SW");
define("IUP_MOVE","MOVE");
define("IUP_HAND","HAND");
define("IUP_NONE","NONE");
define("IUP_IUP","IUP");
define("IUP_CROSS","CROSS");
define("IUP_PEN","PEN");
define("IUP_TEXT","TEXT");
define("IUP_RESIZE_C","RESIZE_C");
define("IUP_OPENHAND","OPENHAND");
define("IUP_K_exclam","K_exclam");
define("IUP_K_quotedbl","K_quotedbl");
define("IUP_K_numbersign","K_numbersign");
define("IUP_K_dollar","K_dollar");
define("IUP_K_percent","K_percent");
define("IUP_K_ampersand","K_ampersand");
define("IUP_K_quoteright","K_quoteright");
define("IUP_K_parentleft","K_parentleft");
define("IUP_K_parentright","K_parentright");
define("IUP_K_asterisk","K_asterisk");
define("IUP_K_plus","K_plus");
define("IUP_K_comma","K_comma");
define("IUP_K_minus","K_minus");
define("IUP_K_period","K_period");
define("IUP_K_slash","K_slash");
define("IUP_K_0","K_0");
define("IUP_K_1","K_1");
define("IUP_K_2","K_2");
define("IUP_K_3","K_3");
define("IUP_K_4","K_4");
define("IUP_K_5","K_5");
define("IUP_K_6","K_6");
define("IUP_K_7","K_7");
define("IUP_K_8","K_8");
define("IUP_K_9","K_9");
define("IUP_K_colon","K_colon");
define("IUP_K_semicolon","K_semicolon ");
define("IUP_K_less","K_less");
define("IUP_K_equal","K_equal");
define("IUP_K_greater","K_greater");
define("IUP_K_question","K_question");
define("IUP_K_at","K_at");
define("IUP_K_A","K_A");
define("IUP_K_B","K_B");
define("IUP_K_C","K_C");
define("IUP_K_D","K_D");
define("IUP_K_E","K_E");
define("IUP_K_F","K_F");
define("IUP_K_G","K_G");
dixyes commented 5 months ago

内存泄漏应该不会core啊(sfxname是全生命周期的 也算不上泄露)

我猜事php改什么东西了,等我收拾完这波重构看一眼咋回事

dixyes commented 5 months ago

最小复现demo,参见这个issue(crazywhalecc/static-php-cli#460)

<?php
define("K_SP"," ");
...

内存泄露快速修了下: https://github.com/dixyes/phpmicro/commit/9d84d145621b7ac869cf97c16e3db93c1d589377 ,但应该和它没关系,zend内存池寄了才会报zend_mm_heap corrupted

Windows 11 VS2022 php8.3.7

无法复现

最脑阔疼的地方就是 没有demo -> 有了demo不复现

能的话把你的带调试符号的二进制发一下(没有敏感信息的话直接issue附件就行) 我来看看咋回事

dixyes commented 5 months ago

@avriltank 你可以试试环境变量USE_ZEND_ALLOC=0 然后跑一下程序,看他core不

avriltank commented 5 months ago

USE_ZEND_ALLOC=0一样,我感觉是hook那里导致的,特别是拼接phar的时候,容易有问题。我后边参考你的方式,在windows下全部用resource实现了,一个类似的东西。

avriltank commented 5 months ago
/*
   +----------------------------------------------------------------------+
   | Copyright (c) The PHP Group                                          |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | https://www.php.net/license/3_01.txt                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Edin Kadribasic <edink@php.net>                              |
   |         Marcus Boerger <helly@php.net>                               |
   |         Johannes Schlueter <johannes@php.net>                        |
   |         Parts based on CGI SAPI Module by                            |
   |         Rasmus Lerdorf, Stig Bakken and Zeev Suraski                 |
   +----------------------------------------------------------------------+
*/

#include "php.h"
#include "php_globals.h"
#include "php_variables.h"
#include "php_ini_builder.h"
#include "zend_hash.h"
#include "zend_modules.h"
#include "zend_interfaces.h"

#include "ext/reflection/php_reflection.h"

#include "SAPI.h"

#include <stdio.h>
#include "php.h"
#ifdef PHP_WIN32
#include "win32/time.h"
#include "win32/signal.h"
#include "win32/console.h"
#include <process.h>
#include <shellapi.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <signal.h>
#include <locale.h>
#include "zend.h"
#include "zend_extensions.h"
#include "php_ini.h"
#include "php_globals.h"
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
#include "ext/standard/dl_arginfo.h"
#include "cli.h"
#ifdef PHP_WIN32
#include <io.h>
#include <fcntl.h>
#include "win32/php_registry.h"
#endif

#ifdef __riscos__
#include <unixlib/local.h>
#endif

#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_exceptions.h"

#include "php_getopt.h"

#include "ps_title.h"
#include "php_cli_process_title.h"
#include "php_cli_process_title_arginfo.h"

#ifndef PHP_WIN32
# define php_select(m, r, w, e, t)  select(m, r, w, e, t)
#else
# include "win32/select.h"
#endif

#if defined(PHP_WIN32) && defined(HAVE_OPENSSL)
# include "openssl/applink.c"
#endif

PHPAPI extern char *php_ini_opened_path;
PHPAPI extern char *php_ini_scanned_path;
PHPAPI extern char *php_ini_scanned_files;

#if defined(PHP_WIN32)
#if defined(ZTS)
//ZEND_TSRMLS_CACHE_DEFINE()
#endif
static DWORD orig_cp = 0;
#endif

#ifndef O_BINARY
#define O_BINARY 0
#endif

#define PHP_MODE_STANDARD      1
#define PHP_MODE_HIGHLIGHT     2
#define PHP_MODE_LINT          4
#define PHP_MODE_STRIP         5
#define PHP_MODE_CLI_DIRECT    6
#define PHP_MODE_PROCESS_STDIN 7
#define PHP_MODE_REFLECTION_FUNCTION    8
#define PHP_MODE_REFLECTION_CLASS       9
#define PHP_MODE_REFLECTION_EXTENSION   10
#define PHP_MODE_REFLECTION_EXT_INFO    11
#define PHP_MODE_REFLECTION_ZEND_EXTENSION 12
#define PHP_MODE_SHOW_INI_CONFIG        13

cli_shell_callbacks_t cli_shell_callbacks = { NULL, NULL, NULL };
PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks(void)
{
    return &cli_shell_callbacks;
}

const char HARDCODED_INI[] =
"memory_limit=2G\n"
"opcache.enable = 1\n"
"opcache.enable_cli = 1\n"
"opcache.memory_consumption=128\n"
"opcache.interned_strings_buffer=32\n"
"opcache.max_accelerated_files=80000\n"
"opcache.revalidate_freq=60\n"
"opcache.fast_shutdown=1\n"
"opcache.jit_buffer_size=128m\n"
"opcache.jit=1255\n"
"opcache.save_comments=0\n"
"ffi.enable=1\n"
"phar.readonly=0\n"
"date.timezone = Asia/Shanghai\n"
    "html_errors=0\n"
    "register_argc_argv=1\n"
    "implicit_flush=1\n"
    "output_buffering=0\n"
    "max_execution_time=0\n"
    "max_input_time=-1\n";

const opt_struct OPTIONS[] = {
    {'a', 0, "interactive"},
    {'B', 1, "process-begin"},
    {'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */
    {'c', 1, "php-ini"},
    {'d', 1, "define"},
    {'E', 1, "process-end"},
    {'e', 0, "profile-info"},
    {'F', 1, "process-file"},
    {'f', 1, "file"},
    {'h', 0, "help"},
    {'i', 0, "info"},
    {'l', 0, "syntax-check"},
    {'m', 0, "modules"},
    {'n', 0, "no-php-ini"},
    {'q', 0, "no-header"}, /* for compatibility with CGI (do not generate HTTP headers) */
    {'R', 1, "process-code"},
    {'H', 0, "hide-args"},
    {'r', 1, "run"},
    {'s', 0, "syntax-highlight"},
    {'s', 0, "syntax-highlighting"},
    {'S', 1, "server"},
    {'t', 1, "docroot"},
    {'w', 0, "strip"},
    {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
    {'v', 0, "version"},
    {'z', 1, "zend-extension"},
    {10,  1, "rf"},
    {10,  1, "rfunction"},
    {11,  1, "rc"},
    {11,  1, "rclass"},
    {12,  1, "re"},
    {12,  1, "rextension"},
    {13,  1, "rz"},
    {13,  1, "rzendextension"},
    {14,  1, "ri"},
    {14,  1, "rextinfo"},
    {15,  0, "ini"},
    /* Internal testing option -- may be changed or removed without notice,
     * including in patch releases. */
    {16,  1, "repeat"},
    {'-', 0, NULL} /* end of args */
};

#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif

static inline bool sapi_cli_select(php_socket_t fd)
{
    fd_set wfd;
    struct timeval tv;
    int ret;

    FD_ZERO(&wfd);

    PHP_SAFE_FD_SET(fd, &wfd);

    tv.tv_sec = (long)FG(default_socket_timeout);
    tv.tv_usec = 0;

    ret = php_select(fd+1, NULL, &wfd, NULL, &tv);

    return ret != -1;
}

PHP_CLI_API ssize_t sapi_cli_single_write(const char *str, size_t str_length) /* {{{ */
{
    ssize_t ret;

    if (cli_shell_callbacks.cli_shell_write) {
        cli_shell_callbacks.cli_shell_write(str, str_length);
    }

#ifdef PHP_WRITE_STDOUT
    do {
        ret = write(STDOUT_FILENO, str, str_length);
    } while (ret <= 0 && (errno == EINTR || (errno == EAGAIN && sapi_cli_select(STDOUT_FILENO))));
#else
    ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
    if (ret == 0 && ferror(stdout)) {
        return -1;
    }
#endif
    return ret;
}
/* }}} */

static size_t sapi_cli_ub_write(const char *str, size_t str_length) /* {{{ */
{
    const char *ptr = str;
    size_t remaining = str_length;
    ssize_t ret;

    if (!str_length) {
        return 0;
    }

    if (cli_shell_callbacks.cli_shell_ub_write) {
        size_t ub_wrote;
        ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length);
        if (ub_wrote != (size_t) -1) {
            return ub_wrote;
        }
    }

    while (remaining > 0)
    {
        ret = sapi_cli_single_write(ptr, remaining);
        if (ret < 0) {
#ifndef PHP_CLI_WIN32_NO_CONSOLE
            EG(exit_status) = 255;
            php_handle_aborted_connection();
#endif
            break;
        }
        ptr += ret;
        remaining -= ret;
    }

    return (ptr - str);
}
/* }}} */

static void sapi_cli_flush(void *server_context) /* {{{ */
{
    /* Ignore EBADF here, it's caused by the fact that STDIN/STDOUT/STDERR streams
     * are/could be closed before fflush() is called.
     */
    if (fflush(stdout)==EOF && errno!=EBADF) {
#ifndef PHP_CLI_WIN32_NO_CONSOLE
        php_handle_aborted_connection();
#endif
    }
}
/* }}} */

static char *php_self = "";
static char *script_filename = "";

static void sapi_cli_register_variables(zval *track_vars_array) /* {{{ */
{
    size_t len;
    char   *docroot = "";

    /* In CGI mode, we consider the environment to be a part of the server
     * variables
     */
    php_import_environment_variables(track_vars_array);

    /* Build the special-case PHP_SELF variable for the CLI version */
    len = strlen(php_self);
    if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, len, &len)) {
        php_register_variable("PHP_SELF", php_self, track_vars_array);
    }
    if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &php_self, len, &len)) {
        php_register_variable("SCRIPT_NAME", php_self, track_vars_array);
    }
    /* filenames are empty for stdin */
    len = strlen(script_filename);
    if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &script_filename, len, &len)) {
        php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array);
    }
    if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &script_filename, len, &len)) {
        php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array);
    }
    /* just make it available */
    len = 0U;
    if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len)) {
        php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array);
    }
}
/* }}} */

static void sapi_cli_log_message(const char *message, int syslog_type_int) /* {{{ */
{
    fprintf(stderr, "%s\n", message);
#ifdef PHP_WIN32
    fflush(stderr);
#endif
}
/* }}} */

static int sapi_cli_deactivate(void) /* {{{ */
{
    fflush(stdout);
    if(SG(request_info).argv0) {
        free(SG(request_info).argv0);
        SG(request_info).argv0 = NULL;
    }
    return SUCCESS;
}
/* }}} */

static char* sapi_cli_read_cookies(void) /* {{{ */
{
    return NULL;
}
/* }}} */

static int sapi_cli_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s) /* {{{ */
{
    return 0;
}
/* }}} */

static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
{
    /* We do nothing here, this function is needed to prevent that the fallback
     * header handling is called. */
    return SAPI_HEADER_SENT_SUCCESSFULLY;
}
/* }}} */

static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_context) /* {{{ */
{
}
/* }}} */

static int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */
{
    return php_module_startup(sapi_module, NULL);
}
/* }}} */

/* {{{ sapi_cli_ini_defaults */

/* overwritable ini defaults must be set in sapi_cli_ini_defaults() */
#define INI_DEFAULT(name,value)\
    ZVAL_NEW_STR(&tmp, zend_string_init(value, sizeof(value)-1, 1));\
    zend_hash_str_update(configuration_hash, name, sizeof(name)-1, &tmp);\

static void sapi_cli_ini_defaults(HashTable *configuration_hash)
{
    zval tmp;
    INI_DEFAULT("display_errors", "1");
}
/* }}} */

/* {{{ sapi_module_struct cli_sapi_module */
static sapi_module_struct cli_sapi_module = {
    "cli",                          /* name */
    "Command Line Interface",       /* pretty name */

    php_cli_startup,                /* startup */
    php_module_shutdown_wrapper,    /* shutdown */

    NULL,                           /* activate */
    sapi_cli_deactivate,            /* deactivate */

    sapi_cli_ub_write,              /* unbuffered write */
    sapi_cli_flush,                 /* flush */
    NULL,                           /* get uid */
    NULL,                           /* getenv */

    php_error,                      /* error handler */

    sapi_cli_header_handler,        /* header handler */
    sapi_cli_send_headers,          /* send headers handler */
    sapi_cli_send_header,           /* send header handler */

    NULL,                           /* read POST data */
    sapi_cli_read_cookies,          /* read Cookies */

    sapi_cli_register_variables,    /* register server variables */
    sapi_cli_log_message,           /* Log message */
    NULL,                           /* Get request time */
    NULL,                           /* Child terminate */

    STANDARD_SAPI_MODULE_PROPERTIES
};
/* }}} */

static const zend_function_entry additional_functions[] = {
    ZEND_FE(dl, arginfo_dl)
    PHP_FE(cli_set_process_title,        arginfo_cli_set_process_title)
    PHP_FE(cli_get_process_title,        arginfo_cli_get_process_title)
    PHP_FE_END
};

static php_stream *s_in_process = NULL;

static void cli_register_file_handles(void)
{
    php_stream *s_in, *s_out, *s_err;
    php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL;
    zend_constant ic, oc, ec;

    s_in  = php_stream_open_wrapper_ex("php://stdin",  "rb", 0, NULL, sc_in);
    s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out);
    s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err);

    /* Release stream resources, but don't free the underlying handles. Otherwise,
     * extensions which write to stderr or company during mshutdown/gshutdown
     * won't have the expected functionality.
     */
    if (s_in) s_in->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE;
    if (s_out) s_out->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE;
    if (s_err) s_err->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE;

    if (s_in==NULL || s_out==NULL || s_err==NULL) {
        if (s_in) php_stream_close(s_in);
        if (s_out) php_stream_close(s_out);
        if (s_err) php_stream_close(s_err);
        return;
    }

    s_in_process = s_in;

    php_stream_to_zval(s_in,  &ic.value);
    php_stream_to_zval(s_out, &oc.value);
    php_stream_to_zval(s_err, &ec.value);

    Z_CONSTANT_FLAGS(ic.value) = 0;
    ic.name = zend_string_init_interned("STDIN", sizeof("STDIN")-1, 0);
    zend_register_constant(&ic);

    Z_CONSTANT_FLAGS(oc.value) = 0;
    oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT")-1, 0);
    zend_register_constant(&oc);

    Z_CONSTANT_FLAGS(ec.value) = 0;
    ec.name = zend_string_init_interned("STDERR", sizeof("STDERR")-1, 0);
    zend_register_constant(&ec);
}

/* {{{ cli_seek_file_begin */
/*
static zend_result cli_seek_file_begin(zend_file_handle *file_handle, char *script_file)
{
    FILE *fp = VCWD_FOPEN(script_file, "rb");
    if (!fp) {
        fprintf(stderr, "Could not open input file: %s\n", script_file);
        return FAILURE;
    }

    zend_stream_init_fp(file_handle, fp, script_file);
    file_handle->primary_script = 1;
    return SUCCESS;
}
*/
/* }}} */

/*{{{ php_cli_win32_ctrl_handler */
#if defined(PHP_WIN32)
BOOL WINAPI php_cli_win32_ctrl_handler(DWORD sig)
{
    (void)php_win32_cp_cli_do_restore(orig_cp);

    return FALSE;
}
#endif
/*}}}*/

static int do_cli(int argc, char **argv,void* pData,DWORD dataSize,char* which_run_type) /* {{{ */
{
    int c;
    zend_file_handle file_handle;
    volatile int request_started = 0;
    char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL;
    char *translated_path = NULL;
    char *script_file = NULL;

    file_handle.filename = NULL;

    char tempFileName[L_tmpnam_s];
    FILE *tempFile;

    if (tmpnam_s(tempFileName, L_tmpnam_s) != 0) {
        printf("Failed to generate temporary file name\n");
        goto err;
    }
    if(strcmp("php",which_run_type)!=0)
    {
        strcat(tempFileName,".phar");
    }

    script_file = tempFileName;

    zend_try {

        CG(in_compilation) = 0; /* not initialized but needed for several options */

        /* Set some CLI defaults */
        SG(options) |= SAPI_OPTION_NO_CHDIR;

        virtual_cwd_activate();

        tempFile = VCWD_FOPEN(tempFileName, "wb+");
        if (tempFile == NULL) {
            printf("Failed to create temporary file\n");
            goto err;
        }

        if(fwrite(pData, dataSize, 1,tempFile)!=1){
            printf("chenfa: Failed to write temp file.\n");
            fclose(tempFile);
            goto err;
        }
        rewind(tempFile);

        zend_stream_init_fp(&file_handle,tempFile,script_file);
        file_handle.primary_script = 1;
        char real_path[MAXPATHLEN];
        if (VCWD_REALPATH(script_file, real_path)) {
            translated_path = strdup(real_path);
        }
        script_filename = script_file;
        php_self = script_file;

        /* before registering argv to module exchange the *new* argv[0] */
        /* we can achieve this without allocating more memory */
        SG(request_info).argc=argc;
        SG(request_info).path_translated = translated_path ? translated_path : php_self;
        SG(request_info).argv=argv;

        if (php_request_startup()==FAILURE) {
            PUTS("Could not startup.\n");
            goto err;
        }
        request_started = 1;
        CG(skip_shebang) = 1;

        zend_register_bool_constant(
            ZEND_STRL("PHP_CLI_PROCESS_TITLE"),
            is_ps_title_available() == PS_TITLE_SUCCESS,
            0, 0);

        zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER));

        PG(during_request_startup) = 0;

        cli_register_file_handles();

        php_execute_script(&file_handle);

    } zend_end_try();

out:
    if (file_handle.filename) {
        zend_destroy_file_handle(&file_handle);
        unlink(tempFileName);
    }
    if (request_started) {
        php_request_shutdown((void *) 0);
        request_started = 0;
    }
    if (translated_path) {
        free(translated_path);
        translated_path = NULL;
    }

    return EG(exit_status);
err:
    sapi_deactivate();
    zend_ini_deactivate();
    EG(exit_status) = 1;
    goto out;
}
/* }}} */

/* {{{ main */
#ifdef PHP_CLI_WIN32_NO_CONSOLE
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
#else
int main(int argc, char *argv[])
#endif
{

#if defined(PHP_WIN32)
    php_win32_init_gettimeofday();
    if (!php_win32_ioutil_init()) {
        fprintf(stderr, "ioutil initialization failed");
        return 1;
    }
# ifdef PHP_CLI_WIN32_NO_CONSOLE
    int argc = __argc;
    char **argv = __argv;
# endif
    int num_args;
    wchar_t **argv_wide;
    char **argv_save = argv;
    BOOL using_wide_argv = 0;
#endif

    char which_run_type[100];

    int resultSS = LoadStringA(NULL, 1121, which_run_type, 100);
    if (resultSS == 0) {
        printf("find the  Type is NULL");
        return 1;
    }

    HRSRC hResInfo = FindResourceA(NULL, MAKEINTRESOURCEA(1122), RT_RCDATA);
    if (hResInfo == NULL) {
        printf("Failed to find my1\n");
        return 1;
    }

    void* hResData = LoadResource(NULL, hResInfo);
    if (hResData == NULL) {
        printf("Failed to load my2\n");
        return 1;
    }

    LPVOID pData = LockResource(hResData);
    if (pData == NULL || strlen(pData)==0) {
        printf("Failed to lock my3\n");
        return 1;
    }

    DWORD dataSize = SizeofResource(NULL, hResInfo);
    if(dataSize==0)
    {
        printf("Failed to execute empty\n");
        return 1;
    }

    int c;
    int exit_status = SUCCESS;
    int module_started = 0, sapi_started = 0;
    int use_extended_info = 0;
    char *ini_path_override = NULL;
    struct php_ini_builder ini_builder;
    int ini_ignore = 0;
    sapi_module_struct *sapi_module = &cli_sapi_module;

    /*
     * Do not move this initialization. It needs to happen before argv is used
     * in any way.
     */
    argv = save_ps_args(argc, argv);

#if defined(PHP_WIN32) && !defined(PHP_CLI_WIN32_NO_CONSOLE)
    php_win32_console_fileno_set_vt100(STDOUT_FILENO, TRUE);
    php_win32_console_fileno_set_vt100(STDERR_FILENO, TRUE);
#endif

    cli_sapi_module.additional_functions = additional_functions;

#if defined(SIGPIPE) && defined(SIG_IGN)
    signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
                                that sockets created via fsockopen()
                                don't kill PHP if the remote site
                                closes it.  in apache|apxs mode apache
                                does that for us!  thies@thieso.net
                                20000419 */
#endif

#ifdef ZTS
    php_tsrm_startup();
# ifdef PHP_WIN32
    ZEND_TSRMLS_CACHE_UPDATE();
# endif
#endif

    zend_signal_startup();

#ifdef PHP_WIN32
    _fmode = _O_BINARY;         /*sets default for file streams to binary */
    setmode(_fileno(stdin), O_BINARY);      /* make the stdio mode be binary */
    setmode(_fileno(stdout), O_BINARY);     /* make the stdio mode be binary */
    setmode(_fileno(stderr), O_BINARY);     /* make the stdio mode be binary */
#endif

    php_ini_builder_init(&ini_builder);

exit_loop:

    sapi_module->ini_defaults = sapi_cli_ini_defaults;
    sapi_module->php_ini_path_override = ini_path_override;
    sapi_module->phpinfo_as_text = 1;
    sapi_module->php_ini_ignore_cwd = 1;
    sapi_startup(sapi_module);
    sapi_started = 1;

    sapi_module->php_ini_ignore = ini_ignore;

    sapi_module->executable_location = argv[0];

    if (sapi_module == &cli_sapi_module) {
        php_ini_builder_prepend_literal(&ini_builder, HARDCODED_INI);
    }

    sapi_module->ini_entries = php_ini_builder_finish(&ini_builder);

    /* startup after we get the above ini override se we get things right */
    if (sapi_module->startup(sapi_module) == FAILURE) {
        /* there is no way to see if we must call zend_ini_deactivate()
         * since we cannot check if EG(ini_directives) has been initialized
         * because the executor's constructor does not set initialize it.
         * Apart from that there seems no need for zend_ini_deactivate() yet.
         * So we goto out_err.*/
        exit_status = 1;
        goto out;
    }
    module_started = 1;

#if defined(PHP_WIN32)
    php_win32_cp_cli_setup();
    orig_cp = (php_win32_cp_get_orig())->id;
    /* Ignore the delivered argv and argc, read from W API. This place
        might be too late though, but this is the earliest place ATW
        we can access the internal charset information from PHP. */
    argv_wide = CommandLineToArgvW(GetCommandLineW(), &num_args);
    PHP_WIN32_CP_W_TO_ANY_ARRAY(argv_wide, num_args, argv, argc)
    using_wide_argv = 1;

    SetConsoleCtrlHandler(php_cli_win32_ctrl_handler, TRUE);
#endif

    /* -e option */
    if (use_extended_info) {
        CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
    }

    zend_first_try {
#ifndef PHP_CLI_WIN32_NO_CONSOLE
        if (sapi_module == &cli_sapi_module) {
#endif
            exit_status = do_cli(argc, argv,pData,dataSize,which_run_type);
#ifndef PHP_CLI_WIN32_NO_CONSOLE
        }
#endif
    } zend_end_try();
out:
    if (ini_path_override) {
        free(ini_path_override);
    }
    php_ini_builder_deinit(&ini_builder);
    if (module_started) {
        php_module_shutdown();
    }
    if (sapi_started) {
        sapi_shutdown();
    }
#ifdef ZTS
    tsrm_shutdown();
#endif

#if defined(PHP_WIN32)
    (void)php_win32_cp_cli_restore();

    if (using_wide_argv) {
        PHP_WIN32_CP_FREE_ARRAY(argv, argc);
        LocalFree(argv_wide);
    }
    argv = argv_save;
#endif
    /*
     * Do not move this de-initialization. It needs to happen right before
     * exiting.
     */
    cleanup_ps_args(argv);
    exit(exit_status);
}
/* }}} */
avriltank commented 5 months ago

其实micro的实现是最科学的,只需要拼接,偏移下就可以。上边这种实现方式,需要释放出,资源文件中的phar文件,如果是单php文件,可以直接zend_execute,但是phar,我看php代码是用的phar_open_from_filename,必须要从本地文件一个存在的文件包里边去获取转换成phar结构体,其实修改phar源码也可以实现(直接从资源文件流转换到php stream),不释放到本地,只是太麻烦了

avriltank commented 5 months ago

明天我抽个时间,把一个debug的带符号的,micro发你下。你复现内存泄漏的例子,可以用这个编译好的https://dl.static-php.dev/static-php-cli/windows/spc-min/php-8.3.7-micro-win.zip 拼接我给的iup的那个php例子。

<?php
define("K_SP"," ");
define("K_exclam","!");
define("K_quotedbl","\"");
define("K_numbersign","#");
define("K_dollar","$");
define("K_percent","%");
define("K_ampersand","&");
define("K_apostrophe","'");
define("K_parentleft","(");
define("K_parentright",")");
define("K_asterisk","*");
define("K_plus","+");
define("K_comma",",");
define("K_minus","-");
define("K_period",".");
define("K_slash","/");
define("K_0","0");
define("K_1","1");
define("K_2","2");
define("K_3","3");
define("K_4","4");
define("K_5","5");
define("K_6","6");
define("K_7","7");
define("K_8","8");
define("K_9","9");
define("K_colon",":");
define("K_semicolon",";");
define("K_less","<");
define("K_equal","=");
define("K_greater",">");
define("K_question","?");
define("K_at","@");
define("K_A","A");
define("K_B","B");
define("K_C","C");
define("K_D","D");
define("K_E","E");
define("K_F","F");
define("K_G","G");
define("K_H","H");
define("K_I","I");
define("K_J","J");
define("K_K","K");
define("K_L","L");
define("K_M","M");
define("K_N","N");
define("K_O","O");
define("K_P","P");
define("K_Q","Q");
define("K_R","R");
define("K_S","S");
define("K_T","T");
define("K_U","U");
define("K_V","V");
define("K_W","W");
define("K_X","X");
define("K_Y","Y");
define("K_Z","Z");
define("K_bracketleft","[");
define("K_bracketright","]");
define("K_circum","^");
define("K_underscore","_");
define("K_grave","`");
define("K_a","a");
define("K_b","b");
define("K_c","c");
define("K_d","d");
define("K_e","e");
define("K_f","f");
define("K_g","g");
define("K_h","h");
define("K_i","i");
define("K_j","j");
define("K_k","k");
define("K_l","l");
define("K_m","m");
define("K_n","n");
define("K_o","o");
define("K_p","p");
define("K_q","q");
define("K_r","r");
define("K_s","s");
define("K_t","t");
define("K_u","u");
define("K_v","v");
define("K_w","w");
define("K_x","x");
define("K_y","y");
define("K_z","z");
define("K_braceleft","{");
define("K_bar","|");
define("K_braceright","}");
define("K_tilde","~");
define("K_BS","\b");
define("K_TAB","\t");
define("K_LF","\n");
define("K_CR","\r");
define("K_quoteleft","`");
define("K_quoteright","'");
define("K_PAUSE",65299);
define("K_ESC",65307);
define("K_HOME",65360);
define("K_LEFT",65361);
define("K_UP",65362);
define("K_RIGHT",65363);
define("K_DOWN",65364);
define("K_PGUP",65365);
define("K_PGDN",65366);
define("K_END",65367);
define("K_MIDDLE",65291);
define("K_Print",65377);
define("K_INS",65379);
define("K_Menu",65383);
define("K_DEL",65535);
define("K_F1",65470);
define("K_F2",65471);
define("K_F3",65472);
define("K_F4",65473);
define("K_F5",65474);
define("K_F6",65475);
define("K_F7",65476);
define("K_F8",65477);
define("K_F9",65478);
define("K_F10",65479);
define("K_F11",65480);
define("K_F12",65481);
define("K_F13",65482);
define("K_F14",65483);
define("K_F15",65484);
define("K_F16",65485);
define("K_F17",65486);
define("K_F18",65487);
define("K_F19",65488);
define("K_F20",65489);
define("K_LSHIFT",65505);
define("K_RSHIFT",65506);
define("K_LCTRL",65507);
define("K_RCTRL",65508);
define("K_LALT",65513);
define("K_RALT",65514);
define("K_NUM",65407);
define("K_SCROLL",65300);
define("K_CAPS",65509);
define("K_CLEAR",65490);
define("K_HELP",65491);
define("K_ccedilla",231);
define("K_Ccedilla",199);
define("K_acute",180);
define("K_diaeresis",168);
define("IUP_RUN","RUN");
define("IUP_ENGLISH","ENGLISH");
define("IUP_PORTUGUESE","PORTUGUESE");
define("IUP_SBH","SBH");
define("IUP_SBV","SBV");
define("IUP_IDLE_ACTION","IDLE_ACTION");
define("IUP_ACTION","ACTION");
define("IUP_GETFOCUS_CB","GETFOCUS_CB");
define("IUP_KILLFOCUS_CB","KILLFOCUS_CB");
define("IUP_K_ANY","K_ANY");
define("IUP_KEYPRESS_CB","KEYPRESS_CB");
define("IUP_HELP_CB","HELP_CB");
define("IUP_SCROLL_CB","SCROLL_CB");
define("IUP_RESIZE_CB","RESIZE_CB");
define("IUP_MOTION_CB","MOTION_CB");
define("IUP_BUTTON_CB","BUTTON_CB");
define("IUP_ENTERWINDOW_CB","ENTERWINDOW_CB");
define("IUP_LEAVEWINDOW_CB","LEAVEWINDOW_CB");
define("IUP_WHEEL_CB","WHEEL_CB");
define("IUP_MASK_CB","MASK_CB");
define("IUP_OPEN_CB","OPEN_CB");
define("IUP_HIGHLIGHT_CB","HIGHLIGHT_CB");
define("IUP_MENUCLOSE_CB","MENUCLOSE_CB");
define("IUP_MAP_CB","MAP_CB");
define("IUP_CLOSE_CB","CLOSE_CB");
define("IUP_SHOW_CB","SHOW_CB");
define("IUP_DROPFILES_CB","DROPFILES_CB");
define("IUP_WOM_CB","WOM_CB");
define("IUP_DIRECTION","DIRECTION");
define("IUP_ACTIVE","ACTIVE");
define("IUP_BGCOLOR","BGCOLOR");
define("IUP_FRAMECOLOR","FRAMECOLOR");
define("IUP_FGCOLOR","FGCOLOR");
define("IUP_COLOR","COLOR");
define("IUP_WID","WID");
define("IUP_SIZE","SIZE");
define("IUP_RASTERSIZE","RASTERSIZE");
define("IUP_TITLE","TITLE");
define("IUP_VALUE","VALUE");
define("IUP_VISIBLE","VISIBLE");
define("IUP_FONT","FONT");
define("IUP_TIP","TIP");
define("IUP_EXPAND","EXPAND");
define("IUP_SEPARATOR","SEPARATOR");
define("IUP_HOTSPOT","HOTSPOT");
define("IUP_HEIGHT","HEIGHT");
define("IUP_WIDTH","WIDTH");
define("IUP_KEY","KEY");
define("IUP_MULTIPLE","MULTIPLE");
define("IUP_DROPDOWN","DROPDOWN");
define("IUP_VISIBLE_ITEMS","VISIBLE_ITEMS");
define("IUP_MARGIN","MARGIN");
define("IUP_GAP","GAP");
define("IUP_ALIGNMENT","ALIGNMENT");
define("IUP_IMAGE","IMAGE");
define("IUP_IMINACTIVE","IMINACTIVE");
define("IUP_IMPRESS","IMPRESS");
define("IUP_WIN_SAVEBITS","WIN_SAVEBITS");
define("IUP_NC","NC");
define("IUP_MASK","MASK");
define("IUP_APPEND","APPEND");
define("IUP_BORDER","BORDER");
define("IUP_CARET","CARET");
define("IUP_SELECTION","SELECTION");
define("IUP_SELECTEDTEXT","SELECTEDTEXT");
define("IUP_INSERT","INSERT");
define("IUP_CONID","CONID");
define("IUP_CURSOR","CURSOR");
define("IUP_ICON","ICON");
define("IUP_MENUBOX","MENUBOX");
define("IUP_MINBOX","MINBOX");
define("IUP_MAXBOX","MAXBOX");
define("IUP_RESIZE","RESIZE");
define("IUP_MENU","MENU");
define("IUP_STARTFOCUS","STARTFOCUS");
define("IUP_PARENTDIALOG","PARENTDIALOG");
define("IUP_SHRINK","SHRINK");
define("IUP_DEFAULTENTER","DEFAULTENTER");
define("IUP_DEFAULTESC","DEFAULTESC");
define("IUP_X","X");
define("IUP_Y","Y");
define("IUP_TOOLBOX","TOOLBOX");
define("IUP_CONTROL","CONTROL");
define("IUP_READONLY","READONLY");
define("IUP_SCROLLBAR","SCROLLBAR");
define("IUP_POSY","POSY");
define("IUP_POSX","POSX");
define("IUP_DX","DX");
define("IUP_DY","DY");
define("IUP_XMAX","XMAX");
define("IUP_XMIN","XMIN");
define("IUP_YMAX","YMAX");
define("IUP_YMIN","YMIN");
define("IUP_RED","255 0 0");
define("IUP_GREEN","0 255 0");
define("IUP_BLUE","0 0 255");
define("IUP_MIN","MIN");
define("IUP_MAX","MAX");
define("IUP_TIME","TIME");
define("IUP_DRAG","DRAG");
define("IUP_DROP","DROP");
define("IUP_REPAINT","REPAINT");
define("IUP_TOPMOST","TOPMOST");
define("IUP_CLIPCHILDREN","CLIPCHILDREN");
define("IUP_DIALOGTYPE","DIALOGTYPE");
define("IUP_FILE","FILE");
define("IUP_MULTIPLEFILES","MULTIPLEFILES");
define("IUP_FILTER","FILTER");
define("IUP_FILTERUSED","FILTERUSED");
define("IUP_FILTERINFO","FILTERINFO");
define("IUP_EXTFILTER","EXTFILTER");
define("IUP_DIRECTORY","DIRECTORY");
define("IUP_ALLOWNEW","ALLOWNEW");
define("IUP_NOOVERWRITEPROMPT","NOOVERWRITEPROMPT");
define("IUP_NOCHANGEDIR","NOCHANGEDIR");
define("IUP_FILEEXIST","FILEEXIST");
define("IUP_STATUS","STATUS");
define("IUP_LOCKLOOP","LOCKLOOP");
define("IUP_SYSTEM","SYSTEM");
define("IUP_DRIVER","DRIVER");
define("IUP_SCREENSIZE","SCREENSIZE");
define("IUP_SYSTEMLANGUAGE","SYSTEMLANGUAGE");
define("IUP_COMPUTERNAME","COMPUTERNAME");
define("IUP_USERNAME","USERNAME");
define("IUP_OPEN","OPEN");
define("IUP_SAVE","SAVE");
define("IUP_DIR","DIR");
define("IUP_HORIZONTAL","HORIZONTAL");
define("IUP_VERTICAL","VERTICAL");
define("IUP_YES","YES");
define("IUP_NO","NO");
define("IUP_ON","ON");
define("IUP_OFF","OFF");
define("IUP_ACENTER","ACENTER");
define("IUP_ALEFT","ALEFT");
define("IUP_ARIGHT","ARIGHT");
define("IUP_ATOP","ATOP");
define("IUP_ABOTTOM","ABOTTOM");
define("IUP_NORTH","NORTH");
define("IUP_SOUTH","SOUTH");
define("IUP_WEST","WEST");
define("IUP_EAST","EAST");
define("IUP_NE","NE");
define("IUP_SE","SE");
define("IUP_NW","NW");
define("IUP_SW","SW");
define("IUP_FULLSCREEN","FULLSCREEN");
define("IUP_FULL","FULL");
define("IUP_HALF","HALF");
define("IUP_THIRD","THIRD");
define("IUP_QUARTER","QUARTER");
define("IUP_EIGHTH","EIGHTH");
define("IUP_ARROW","ARROW");
define("IUP_BUSY","BUSY");
define("IUP_RESIZE_N","RESIZE_N");
define("IUP_RESIZE_S","RESIZE_S");
define("IUP_RESIZE_E","RESIZE_E");
define("IUP_RESIZE_W","RESIZE_W");
define("IUP_RESIZE_NE","RESIZE_NE");
define("IUP_RESIZE_NW","RESIZE_NW");
define("IUP_RESIZE_SE","RESIZE_SE");
define("IUP_RESIZE_SW","RESIZE_SW");
define("IUP_MOVE","MOVE");
define("IUP_HAND","HAND");
define("IUP_NONE","NONE");
define("IUP_IUP","IUP");
define("IUP_CROSS","CROSS");
define("IUP_PEN","PEN");
define("IUP_TEXT","TEXT");
define("IUP_RESIZE_C","RESIZE_C");
define("IUP_OPENHAND","OPENHAND");
define("IUP_K_exclam","K_exclam");
define("IUP_K_quotedbl","K_quotedbl");
define("IUP_K_numbersign","K_numbersign");
define("IUP_K_dollar","K_dollar");
define("IUP_K_percent","K_percent");
define("IUP_K_ampersand","K_ampersand");
define("IUP_K_quoteright","K_quoteright");
define("IUP_K_parentleft","K_parentleft");
define("IUP_K_parentright","K_parentright");
define("IUP_K_asterisk","K_asterisk");
define("IUP_K_plus","K_plus");
define("IUP_K_comma","K_comma");
define("IUP_K_minus","K_minus");
define("IUP_K_period","K_period");
define("IUP_K_slash","K_slash");
define("IUP_K_0","K_0");
define("IUP_K_1","K_1");
define("IUP_K_2","K_2");
define("IUP_K_3","K_3");
define("IUP_K_4","K_4");
define("IUP_K_5","K_5");
define("IUP_K_6","K_6");
define("IUP_K_7","K_7");
define("IUP_K_8","K_8");
define("IUP_K_9","K_9");
define("IUP_K_colon","K_colon");
define("IUP_K_semicolon","K_semicolon ");
define("IUP_K_less","K_less");
define("IUP_K_equal","K_equal");
define("IUP_K_greater","K_greater");
define("IUP_K_question","K_question");
define("IUP_K_at","K_at");
define("IUP_K_A","K_A");
define("IUP_K_B","K_B");
define("IUP_K_C","K_C");
define("IUP_K_D","K_D");
define("IUP_K_E","K_E");
define("IUP_K_F","K_F");
define("IUP_K_G","K_G");
dixyes commented 5 months ago

USE_ZEND_ALLOC=0一样,我感觉是hook那里导致的,特别是拼接phar的时候,容易有问题。我后边参考你的方式,在windows下全部用resource实现了,一个类似的东西。

@avriltank

问题有俩

zend_mm_heap corrupt 是内存错误(例如野指针,缓冲区溢出之类的问题)不是内存泄露,USE_ZEND_ALLOC=0会关掉zend内存池,(p)emalloc全走malloc,如果有内存错误就会直接segv炸了,理论上来说 zend_mm_heap corrupt代表了关闭zend内存池后的segv

关于内存泄露,首先单纯内存泄露不会报zend_mm_heap corrupt。在micro中有那么俩变量是全生命周期的,不能算作内存泄漏,除此之外那个文件名的泄露我也修了, 但没推到easysoft的上游(等lwmbs完成一次完整构建验证没问题了再推)

你可以在你的micro 源码上打这个patch: https://github.com/dixyes/phpmicro/commit/9d84d145621b7ac869cf97c16e3db93c1d589377.patch 来看看是不是解决了这个内存泄露,但我觉得改变不了zend_mm_heap corrupt

P.S. 如果configure参数制定了--enable-debug的话,漏内存的zend内存池报错大概长这样:

======= memory leak detected ========
balabala
avriltank commented 5 months ago

线程安全版本,USE_ZEND_ALLOC=0不会core,我整理下文件发给你

avriltank commented 5 months ago

我将所有必备文件打包为静态库和pdb文件了,https://www.123pan.com/s/lKQijv-RXGO.html 您只需要每次编译带上这几个库就行,编译直接build.bat即可,最小main代码,

typedef struct _zend_module_entry zend_module_entry;
typedef enum {
  SUCCESS =  0,
  FAILURE = -1,     /* this MUST stay a negative number, or it may affect functions! */
} ZEND_RESULT_CODE;

typedef ZEND_RESULT_CODE zend_result;

extern zend_result php_register_extensions(zend_module_entry * const * ptr, int count);
extern int main_chenfa(int argc, char *argv[]);

extern zend_module_entry basic_functions_module;
extern zend_module_entry date_module_entry;
extern zend_module_entry hash_module_entry;
extern zend_module_entry json_module_entry;
extern zend_module_entry pcre_module_entry;
extern zend_module_entry random_module_entry;
extern zend_module_entry reflection_module_entry;
extern zend_module_entry spl_module_entry;
extern zend_module_entry phar_module_entry;

static zend_module_entry * const php_builtin_extensions[] = {
    &basic_functions_module,
    &date_module_entry,
    &hash_module_entry,
    &json_module_entry,
    &pcre_module_entry,
    &random_module_entry,
    &reflection_module_entry,
    &spl_module_entry,
    &phar_module_entry,

};
int php_register_internal_extensions(void)
{
    return php_register_extensions(php_builtin_extensions, sizeof(php_builtin_extensions)/sizeof(zend_module_entry*));
}

int main(int argc, char *argv[])
{
    return main_chenfa(argc,argv);
}
dixyes commented 5 months ago

我将所有必备文件打包为静态库和pdb文件了,https://www.123pan.com/s/lKQijv-RXGO.html 您只需要每次编译带上这几个库就行,编译直接build.bat即可,最小main代码,

typedef struct _zend_module_entry zend_module_entry;
typedef enum {
  SUCCESS =  0,
  FAILURE = -1,       /* this MUST stay a negative number, or it may affect functions! */
} ZEND_RESULT_CODE;

typedef ZEND_RESULT_CODE zend_result;

extern zend_result php_register_extensions(zend_module_entry * const * ptr, int count);
extern int main_chenfa(int argc, char *argv[]);

extern zend_module_entry basic_functions_module;
extern zend_module_entry date_module_entry;
extern zend_module_entry hash_module_entry;
extern zend_module_entry json_module_entry;
extern zend_module_entry pcre_module_entry;
extern zend_module_entry random_module_entry;
extern zend_module_entry reflection_module_entry;
extern zend_module_entry spl_module_entry;
extern zend_module_entry phar_module_entry;

static zend_module_entry * const php_builtin_extensions[] = {
    &basic_functions_module,
    &date_module_entry,
    &hash_module_entry,
    &json_module_entry,
    &pcre_module_entry,
    &random_module_entry,
    &reflection_module_entry,
    &spl_module_entry,
    &phar_module_entry,

};
int php_register_internal_extensions(void)
{
  return php_register_extensions(php_builtin_extensions, sizeof(php_builtin_extensions)/sizeof(zend_module_entry*));
}

int main(int argc, char *argv[])
{
    return main_chenfa(argc,argv);
}

你可以用github这个附件功能上传文件的,没看懂你发了个啥。。。

我猜:

  1. 如果你自己实现了个micro类似的功能的sfx或者单二进制的php解释器啥的,这个就和micro无关了,我不介意帮你调下zend内存池问题,但我希望你把它的源码以符合PHP许可证的方式开源到gh/gl/gitee等平台
  2. 如果你需要上面描述的二进制,又不希望开源自己的C源码,你可以使用PHP的embed SAPI,static-php项目有编译这个SAPI的功能。这种情况你应该会用会写php,不需要我来调试,这也跟micro没关系了
  3. 如果你需要帮助调试你的micro二进制,不要对他做太大的修改或者修改了什么也描述一下。这种情况只需要对应的micro.sfx二进制和pdb即可,不需要未链接的.lib。vs只需要这个pdb文件就能调

对于你发的这个东西:缺少php的符号,调试不了,不知道zend内存池有啥地方炸了。我太久没调试过了,怀疑可能是zend现在检测到泄露会abort,但这个不会影响lwmbs或者static-php-cli的构建产物(他们都没开debug,不会检测内存泄露

avriltank commented 5 months ago

大佬你想多了,完全就用的php的代码和你的代码,我是菜鸟,对php底层代码是真不熟悉。只是php那套编译流程是真的繁琐,所以我简化了下,因为静态编译,每次自己开发一个扩展或者修改追踪代码,都要基本全部编译一遍,所以我按照每个扩展,抽离成静态库,简化下编译,方便调试,回头空了我好好研究下php的源码

avriltank commented 5 months ago

上边应该带pdb文件的,你是要官方的php的编译方式的pdb文件?

dixyes commented 5 months ago

上边应该带pdb文件的,你是要官方的php的编译方式的pdb文件?

我hide了一些comment,太长了 有点碍事了

没有php源码的pdb啊 abort是在php的栈里的 但这部分无了

屏幕截图 2024-05-30 164153
avriltank commented 5 months ago

这是怎么玩的,大佬厉害,visual studio,我都还是大一的时候装过一次就卸载了

avriltank commented 5 months ago

我用的cmake编译的,pdb文件,也是开了下,好像缺少php主文件包的pdb文件?应该在zend_static.pdb文件里边

dixyes commented 5 months ago

我开了debug 跑那个php也没问题

那么问题可能是

  1. lwmbs有魔法 -> 换lwmbs的二进制试一试
  2. 我的大refactor不知不觉修了这个问题 -> rebase下你的micro到我的fork https://github.com/dixyes/phpmicro
  3. 你的构建系统哪里写歪了,导致了两次构建的lib ABI不匹配 -> 检查是不是用了不同版本的php头/lib 然后用PHP官方构建系统跑一下
  4. spc有魔法 -> 用PHP官方构建系统跑一下
avriltank commented 5 months ago

3的问题我全部用的libcmtd,不是libcmt,4我可以尝试下,这个issule先留着,我这几天忙完实验报告后,好好研究下php的源码

dixyes commented 5 months ago

3的问题我全部用的libcmtd,不是libcmt,4我可以尝试下,这个issule先留着,我这几天忙完实验报告后,好好研究下php的源码

不是MT MTd这种CRT的不匹配 是各种lib的ABI CRT不匹配直接就报错了

avriltank commented 5 months ago

应该都是用的同种方式编译的。crt应该是匹配的,不管怎样,很感谢大佬的调试,暂时也不清楚是啥原因。

crazywhalecc commented 5 months ago

我也尝试复现一下 mac 上这里之前的问题,好久没看了 //

crazywhalecc commented 5 months ago

macOS 上复现的基本过程如下:

# 编译这些扩展
bin/spc build bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip --build-cli --build-fpm --build-micro --debug --no-strip --enable-zts

# 构建 spc.phar
composer build:phar

# 构建 my-app
bin/spc micro:combine spc.phar

# 调试 my-app
lldb my-app

调试过程如下:

(lldb) target create "my-app"
Current executable set to '/Users/jerry/project/git-project/static-php-cli/my-app' (arm64).
(lldb) run
Process 16847 launched: '/Users/jerry/project/git-project/static-php-cli/my-app' (arm64)
static-php-cli 2.2.2

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display help for the given command. When no command is given display help for the list command
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi|--no-ansi  Force (or disable --no-ansi) ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  build               [build:php] build PHP
  completion          Dump the shell completion script
  del-download        [delete-download|del-down] Remove locked download source or package using name
  doctor              Diagnose whether the current environment can compile normally
  download            [fetch] Download required sources
  dump-license        Dump licenses for required libraries
  extract             [extract-source] Extract required sources
  help                Display help for a command
  install-pkg         [i|install-package] Install additional packages
  list                List commands
  switch-php-version  Switch downloaded PHP version
 build
  build:libs          Build dependencies
 dev
  dev:extensions      [list-ext] Helper command that lists available extension details
  dev:php-version     [dev:php-ver] Returns version of PHP located source directory
 micro
  micro:combine       Combine micro.sfx and php code together
zend_mm_heap corrupted
Process 16847 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x000000019887ea60 libsystem_kernel.dylib`__pthread_kill + 8
libsystem_kernel.dylib`:
->  0x19887ea60 <+8>:  b.lo   0x19887ea80               ; <+40>
    0x19887ea64 <+12>: pacibsp 
    0x19887ea68 <+16>: stp    x29, x30, [sp, #-0x10]!
    0x19887ea6c <+20>: mov    x29, sp
Target 0: (my-app) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x000000019887ea60 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x00000001988b6c20 libsystem_pthread.dylib`pthread_kill + 288
    frame #2: 0x00000001987c3a20 libsystem_c.dylib`abort + 180
    frame #3: 0x00000001008f9164 my-app`zend_mm_panic(message="zend_mm_heap corrupted") at zend_alloc.c:368:2
    frame #4: 0x0000000100901f88 my-app`_efree at zend_alloc.c:1432:4
    frame #5: 0x0000000100901e54 my-app`_efree(ptr=0x0000000102204018) at zend_alloc.c:2612:2
    frame #6: 0x000000010093860c my-app`free_zend_constant(zv=0x000000013806ff00) at zend_constants.c:49:3
    frame #7: 0x0000000100999614 my-app`zend_hash_destroy(ht=0x0000600001e41800) at zend_hash.c:1701:8
    frame #8: 0x0000000100966378 my-app`executor_globals_dtor(executor_globals=0x000000014700dba0) at zend.c:819:3
    frame #9: 0x0000000100869ed4 my-app`ts_free_id(id=8) at TSRM.c:560:8
    frame #10: 0x0000000100966814 my-app`zend_shutdown at zend.c:1127:2
    frame #11: 0x000000010086f810 my-app`php_module_shutdown at main.c:2456:2
    frame #12: 0x0000000100c39354 my-app`main(argc=1, argv=0x000060000096c0e0) at php_micro.c:730:9
    frame #13: 0x000000019852e0e0 dyld`start + 2360
(lldb) q

730 行是 php_module_shutdown();,但具体是哪个 module 导致的还是不太清楚。

avriltank commented 5 months ago
void free_zend_constant(zval *zv)
{
    zend_constant *c = Z_PTR_P(zv);

    if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
        zval_ptr_dtor_nogc(&c->value);
        if (c->name) {
            zend_string_release_ex(c->name, 0);
        }
        efree(c);
    } else {
        zval_internal_ptr_dtor(&c->value);
        if (c->name) {
            zend_string_release_ex(c->name, 1);
        }
        free(c);
    }
}

这里好些有问题

avriltank commented 5 months ago

但这个很奇怪的是,cli模式没问题,唯独micro这边有问题

avriltank commented 5 months ago

可以解决了,把php_micro.c下边代码删了,

        if (SUCCESS == zend_hash_str_del(EG(zend_constants), "PHP_BINARY", sizeof("PHP_BINARY") - 1)) {
            dbgprintf("remake pb constant\n");
            zend_ini_entry *pbentry = NULL;
            if (NULL !=
                (pbentry = zend_hash_str_find_ptr(
                     EG(ini_directives), PHP_MICRO_INIENTRY(php_binary), sizeof(PHP_MICRO_INIENTRY(php_binary)) - 1))) {
                dbgprintf("to %s\n", ZSTR_VAL(pbentry->value));
                REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY",
                    ZSTR_VAL(pbentry->value),
                    ZSTR_LEN(pbentry->value),
                    CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
            } else {
                dbgprintf("removed\n");
                REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
            }
        }
dixyes commented 5 months ago

在Ventura上无法复现, 我还没更Sonoma,我的测试步骤:

git clone https://github.com/php/php-src
git clone https://github.com/dixyes/phpmicro sapi/micro
./buildconf --force
export PATH=/opt/homebrew/Cellar/bison/3.8.2/bin:$PATH
./configure --disable-all --disable-cli --disable-cgi --disable-phpdbg --enable-micro --enable-debug
make micro -j8
./sapi/micro/micro.sfx # 没问题
cat > define.php # 保存测试代码
cat sapi/micro/micro.sfx define.php > define.exe
chmod 0755 define.exe
./define.exe # 没复现
cd sapi/micro
git remote add spc https://github.com/static-php/phpmicro
git fetch spc master
git checkout FETCH_HEAD
git clean -x -f -f -d
popd
./buildconf --force
./configure --disable-all --disable-cli --disable-cgi --disable-phpdbg --enable-micro --enable-debug
make clean
make micro -j8
./sapi/micro/micro.sfx # 没问题
cat sapi/micro/micro.sfx define.php > define.exe
./define.exe # 没复现

linux上我也类似跑了一遍 没复现

dixyes commented 5 months ago

可以解决了,把php_micro.c下边代码删了,

        if (SUCCESS == zend_hash_str_del(EG(zend_constants), "PHP_BINARY", sizeof("PHP_BINARY") - 1)) {
            dbgprintf("remake pb constant\n");
            zend_ini_entry *pbentry = NULL;
            if (NULL !=
                (pbentry = zend_hash_str_find_ptr(
                     EG(ini_directives), PHP_MICRO_INIENTRY(php_binary), sizeof(PHP_MICRO_INIENTRY(php_binary)) - 1))) {
                dbgprintf("to %s\n", ZSTR_VAL(pbentry->value));
                REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY",
                    ZSTR_VAL(pbentry->value),
                    ZSTR_LEN(pbentry->value),
                    CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
            } else {
                dbgprintf("removed\n");
                REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
            }
        }

PHP_BINARY这里确实有魔法,我很怀疑是他的问题,但我没法复现,也没法修

crazywhalecc commented 5 months ago

不带任何扩展或者只带少量或特定的扩展本来就是好的,就上面我提到的那个扩展组合在和 phar 结合后就会出现 zend_mm_heap 错误。

avriltank commented 5 months ago

不带任何扩展或者只带少量或特定的扩展本来就是好的,就上面我提到的那个扩展组合在和 phar 结合后就会出现 zend_mm_heap 错误。

暂时没遇到问题,我基本把php的所有扩展静态编译了。windows下测试没问题

dixyes commented 5 months ago

@avriltank 试试这个https://github.com/dixyes/phpmicro/commit/a96b0d3a8ab4b5f66de5f256b42f7e3ccd219a60.patch

如果没问题我就整理下推easysoft了

avriltank commented 5 months ago

没有问题