请帮我解决PHP代码

时间:2016-01-15 15:36:05

标签: php

在我的代码中有3个部分。必须执行顶部和底部部分。如果输入代码错误,中间部分必须隐藏。

这是我的代码:

 //correct code section. Must execute     
 echo "must show top";        
 //may contain wrong code. But this portion should not affect on lower
 portion code     
 ob_start();     
 // sample wrong code     
 function jk($i){};     
 function jk($i){ echo $i; }';     
 ob_end_clean();   
 //correct code section. Must execute     
 echo "must show bottom";

当前输出:

  

致命错误:无法重新声明jk()(之前......

预期输出:

必须显示top必须显示底部或必须显示顶部

  

致命错误:无法重新声明jk()(之前......

必须显示底部

1 个答案:

答案 0 :(得分:2)

你不能用这个的方式做到这一点,因为PHP文件是在执行 之前编译(到字节码,但无论如何)。

您可以通过将中间部分包装在try / catch中来处理轻微错误,但致命错误仍然会导致整个脚本无效。

所以可以做的是将中间代码放在其他地方,然后从外部访问整个流程范围。如果两个部分需要交换信息(例如一些变量),这可能很棘手。

最简单的方法是将代码保存到临时文件中,然后使用URL get_file_contents从PHP中访问它:

// Construct PHP tag -- hiding it from editor :-)
$prolog = '<'; $prolog .= '?'; $prolog .= "php\n";

// prolog code contains PHP code, but here we treat is as text,
// so all $'s must be escaped. Same goes for epilog.

$prolog .= <<<PROLOG

// This is common code to make what follows work.
// We can pass any data to this script by creating a *second* file
// and passing the name of this second file via GET to avoid POST
// size limits.
// To avoid arbitrary inclusion (just in case), we could check that
// the file name thus passes conforms to a given syntax, e.g. 32
// random hex characters, no URLs or /etc/passwd or funny stuff.
if (isset(\$_GET['envfile'])) {
    \$name = basename(\$_GET['envfile']) . '.txt';
    \$data = unserialize(file_get_contents(\$name));
    unlink(\$name);
} else {
    \$data = null;
}

PROLOG;

$epilog = <<<EPILOG
    // The code is now hopefully loaded and defines a main()
    // function.
    if (!function_exists('main')) {
        die("-ERR: no main function");
    }
    try {
        die(json_encode(main(\$data)));
    } catch (\Exception \$err) {
        die("-ERR: main failed: {\$err->getMessage()}");
    }
EPILOG;

$unique   = uniqid();
// "special dir" is NOT available from THIS site, and is the webroot of another "sandbox" web site
$physical = "./special-dir/{$unique}.php";
// file must contain a full PHP script with tags and all
file_put_contents($physical, $prolog . $code . $epilog);

// Now ask the file to the web server with its "sandbox" personality
$response = file_get_contents("http://sandbox/{$unique}.php");

以上使用的虚拟主机只能从localhost本身访问,(除了谨慎的安全性:禁用敏感功能,在其自己的webroot之外无法访问,...)已打开完整的调试信息和错误报告。

因此,如果您收到PHP错误页面,您就会知道发生了错误(甚至可能会解析它)。否则,脚本可能会返回,例如您可以导入的JSON编码的变量对象:

if (0 === strpos($response, '-ERR')) {
    // $response is a simple error message
}
$package = json_decode($response, true);
if (false === $package) {
    // $response is probably a fatal error HTML page
}
// Do something with $package.

所以回顾一下:

  • 从用户
  • 获取代码
  • 将它与适当的prolog / epilog存根混合到例如引导一些变量使它们可用于“子”脚本,并将数据作为JSON
  • 返回
  • 将生成的代码保存到
  • 的webroot中的临时文件中
  • 带有完整调试的安全“沙盒”网站
  • 调用沙箱URL以生成第二个PHP解释器并查看代码
  • 解释结果

注意:在PHP 7中,新的code parse tree approach可能允许您直接验证代码,而无需保存代码并发送到新的PHP解释器。然后,如果没关系,可以直接 eval(),,但要注意这样做会执行当前脚本范围内的代码,该代码具有更高的权限。您很可能在很短的时间内使用沙箱pwn3d和/或滥用。