我想寫一個c程序,可以分析PHP腳本出於各種原因。我需要從PHP核心庫中調用token_get_all,但我正在爲此苦苦掙扎。我已經靜態編譯php7主分支,並將其鏈接到我的程序。我會發布幾個代碼片段,因爲我已經嘗試了很多方法來調用這個函數,並且一直運行在一種或另一種類型的錯誤中。從c程序調用token_get_all
這個片斷得到,當我執行它最遠:
int main(void)
{
zval function_name, params[1], return_value, param;
ZVAL_NEW_STR(&function_name, zend_string_init("token_get_all", strlen("token_get_all"), 1));
printf("Got here\n");
ZVAL_NEW_STR(¶ms[0], zend_string_init("<?php $x = 1;", strlen("<?php $x = 1;"), 1));
int ret;
printf("Calling function\n");
ret = call_user_function(CG(function_table), NULL, &function_name, &return_value, 1, params TSRMLS_CC);
printf("%i", ret);
}
當它到達call_user_function,它出現segfaults。 Valgrind輸出:
==11451== 1 errors in context 1 of 1:
==11451== Invalid read of size 8
==11451== at 0x40268C: parse_php (parser.c:73)
==11451== by 0x402730: parse_php_file (parser.c:95)
==11451== by 0x4029B2: main (parse-script-main.c:14)
==11451== Address 0x0 is not stack'd, malloc'd or (recently) free'd
parser.c:73是call_user_function的行。
我會發布這個以及,雖然它可能是一個單獨的問題。如果我改變了我初始化函數名或獨立參數的方式,那麼我會用不同的段錯誤結束。試想一下:
int main(void)
{
zval function_name, params[1], return_value, param;
ZVAL_STRING(&function_name, "token_get_all");
printf("Got here\n");
ZVAL_NEW_STR(¶ms[0], zend_string_init("<?php $x = 1;", strlen("<?php $x = 1;"), 1));
int ret;
printf("Calling function\n");
ret = call_user_function(CG(function_table), NULL, &function_name, &return_value, 1, params TSRMLS_CC);
printf("%i", ret);
}
這給了我一個段錯誤的ZVAL_STRING行:
==11481== 1 errors in context 1 of 1:
==11481== Invalid read of size 8
==11481== at 0x407DF5: _emalloc (zend_alloc.c:2376)
==11481== by 0x402559: zend_string_alloc (zend_string.h:121)
==11481== by 0x4025C2: zend_string_init (zend_string.h:157)
==11481== by 0x402639: parse_php (parser.c:65)
==11481== by 0x402747: parse_php_file (parser.c:95)
==11481== by 0x4029C9: main (parse-script-main.c:14)
==11481== Address 0x0 is not stack'd, malloc'd or (recently) free'd
最後,這裏是我的編譯器/連接命令:
gcc -g -D_GNU_SOURCE -Iinclude -I/usr/local/include/php -I/usr/local/include/php/Zend -I/usr/local/include/php/include -I/usr/local/include/php/main -I/usr/local/include/php/ext -I/usr/local/include/php/sapi -I/usr/local/include/php/TSRM -c /path/to/parser.c -o obj/Debug/include/parser.o
g++ -Linclude -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -o bin/Debug/parse-script obj/Debug/include/parser.o obj/Debug/include/project.o obj/Debug/include/utils.o obj/Debug/parse-script-main.o -lphp7 -ldl -lc -lpthread -lgcc
我知道生成的目標文件唐不符合上面的代碼。在上面的例子中,我將問題函數封裝在「int main(void)」中。