php 阻止eval退出程序

wmomyfyw  于 2023-03-28  发布在  PHP
关注(0)|答案(1)|浏览(113)

我正在尝试创建一个PHP“编辑器”,因此,我有一个带有PHP编辑器的表单和一个处理作为输入提交并作为对象返回的代码的文件。
为了捕获一些数据,如执行时间和缓冲区长度,我需要在代码被评估后获取它们。这里的问题是,如果用户使用die终止了程序的执行,它将无法获得这些信息。
这是处理提交的代码的文件:

<?php

$path = $_SERVER['DOCUMENT_ROOT'];
require_once $path . '/wp-load.php';

require WP_PLUGIN_DIR . '/php-editor/vendor/autoload.php';

$output = [];
$data = json_decode( file_get_contents( "php://input" ), true );

// Remove E_WARNING from output
error_reporting(E_ALL ^ E_WARNING);
ini_set('display_errors', true);

if ( $data['data'] ) {
    ob_start();
    $start_time = microtime(1);
    
    try {
        // Execute client's code
        eval( $data['data'] );
    } catch (\Exception $e) {
        $output['output'] = 'N/A';
    }    

    // Generate response
    $output['output'] = ob_get_contents();
    $output['execution_time'] = number_format(microtime(1) - $start_time, 2, '.', '') * 100 . 'ms';
    $output['buffer_length'] = number_format((float)ob_get_length(), 0, ',', '.') . 'B';
    ob_end_clean();

    // Return response as Pretty JSON
    echo json_encode($output, JSON_PRETTY_PRINT);
}

如果用户提交了var_dump("test"); die;(例如),由于程序停止运行die()函数(即使在捕获它之后),因此不会显示任何后续内容,并且不会返回$output对象。如何防止这种情况?

f4t66c6m

f4t66c6m1#

好吧,我应该感谢ChatGPT的这个答案,但由于他还没有回复,我已经改变了我的代码为:

<?php

$path = $_SERVER['DOCUMENT_ROOT'];
require_once $path . '/wp-load.php';

require WP_PLUGIN_DIR . '/php-editor/vendor/autoload.php';

$output = [];
$data = json_decode( file_get_contents( "php://input" ), true );

// Remove E_WARNING from output
error_reporting(E_ALL ^ E_WARNING);
ini_set('display_errors', true);

// Custom output buffer handler
function output_handler($buffer) {
    global $output;
    global $start_time;
    
    $output['output'] = $buffer;
    $output['execution_time'] = number_format(microtime(1) - $start_time, 2, '.', '') * 100 . 'ms';
    $output['buffer_length'] = number_format((float)strlen($buffer), 0, ',', '.') . 'B';
    
    return json_encode($output, JSON_PRETTY_PRINT);
}

if ( $data['data'] ) {
    ob_start('output_handler');
    $start_time = microtime(1);
    
    try {
        // Execute client's code
        eval( $data['data'] );
    } catch (\Exception $e) {
        $output['output'] = 'N/A';
    }
    
    ob_end_flush();
}

我们在这里所做的是用ob_start('output_handler')替换ob_start()。在脚本退出之前自动调用output_handler函数,这允许您计算指标,即使用户使用dieexit退出程序。最后,我们用ob_end_flush()替换ob_end_clean()以刷新缓冲区并将响应发送到客户端。

相关问题