我试图做的C编程在线法官。 当用户进入C代码并提交,我形式重定向到judge.php这是窗体的操作文件。 以下是我已经写在judge.php
<?php
$text=$_POST['code'];
//echo $text;
$var_str = var_export($text, true);
file_put_contents('code.c', $text);
$ans=exec('pwd');
$ans= exec('gcc code.c');
echo $ans;
?>
我已抓获在$文本用户输入并写信给AC文件(code.c)。 到目前为止,它是好的。 但是exec(gcc code.c)
不工作,而不是让任何输出。 我试过其他的linux commnads像PWD,日期等,他们工作的罚款。 什么可能是这种情况的原因,以及如何解决它? 它不是一个目录的问题,我试图exec(pwd)
它给了输出作为其中的代码存在于同一目录下。 我试图从终端上运行相同code.c文件,并运行良好。 所以,这也不是一个“许可”的问题。
还有一两件事,如何呼应如有EXEC()命令无法正常工作产生的错误信息?
从下面的答案得到建议后,我试着
$ CMD = “GCC -std = C99 code.c -g -Wall mysql_config --libs --cflags
-o db_obj.o --pedantic”;
exec($cmd,$out,$status);
但它也不能正常工作。 返回的状态为1
最有可能是权限问题。 “WHOAMI说:”没有人。 请告诉如何主人从没有人更改为根或如何分配,从没有人执行GCC许可
主要从三个方面对我的回答
不当使用的exec
功能。
看看手册页 。 首先, exec
函数的签名是:
string exec ( string $command [, array &$output [, int &$return_var ]] )
因此, exec
可能需要长达3个参数。 它返回的命令输出的最后一行,像文档说明很清楚:
从命令结果的最后一行。 如果你需要执行一个命令,并具有直接传递回不受任何干扰命令的所有数据,使用中继()函数。
要获得执行的命令的输出,一定要设置并使用输出参数。
所以你的情况:
$lastLine = exec($command, $fullOutput, $status);
就是你要找的东西。 如果$status
是什么比别的 0
,你的命令是不成功的。 这就是你应该检查什么做出相应的反应。
任何命令的全部输出可以发现$fullOutput
作为线每线阵列。
输出,如:
all went well
except for this
看起来像这样的在$fullOutput
阵:
array('all went well', 'except for this');
权限可以是一个问题,依然。
你说的权限不太可能是问题的原因,因为你可以运行gcc
在命令行。 所有罚款和花花公子,但什么用户运行在服务器上的PHP脚本?
在网络服务器的情况下,用户通常被称为无人 ,Apache或东西, 用户很可能不会允许运行gcc
。 这是运行任何默认的shell已经成立(bash的,或许)的新实例PHP,这是PHP的用户是登录到该外壳,并且它是正在调用用户gcc
...
知道你是谁,你属于哪个组。 尝试添加给你的脚本:
echo 'Script is running under user: ', exec('whoami'), '<br>', PHP_EOL;
echo 'member of the following groups: ', exec('groups'), '<br>', PHP_EOL;
你问前:是的,这些都是逗号......没有必要来连接,你可以通过多个变量/值echo
,用逗号分隔。 它实际上是快(认为它是C ++的std::cout << some_var << another_var;
一般问题+安全
这一切都成定局:从PHP脚本编译的C代码,你认为它是不是那么简单。 假如我是写这篇文章:
#include <stdio.h>
#include <time.h>
int main ( void )
{
time_t t = time(NULL);
if (t%2)
{
float val = (float) t/2.0;
//do stuff with float...
}
else
{
unsigned long long val = t/2;
//do stuff with unsigned long long...
}
}
你gcc test.c
命令将失败,因为你没有传递参数-std=c99
,例如。
如果我想一个脚本编译一个给定的文件,我还指望该脚本可以让我选择我编这论点,也我的代码-g
, -Wall
和,更不用提:CFLAGS和库(输出pkg-config
或mysql_config --cflags --libs
,仅举我最近使用的具体例)。
基本上,你的脚本,根本无法对付我想要的东西编译与commind像
gcc -std=c99 code.c -g -Wall `mysql_config --libs --cflags` -o db_obj.o --pedantic
这仍然是一个什么样许多编译命令的样子,正在开发调试代码尤其是当一个简化版本。 对于稳定的版本中,你可能会下降-g
和--pedantic
,但你明白我的意思?
试想想它的意思,允许用户通过一组CLI参数,用代码一起。 他们可能会传递一个参数一样-DSOME_MACRO
或-O0
,这意味着它们也可能通过-O0 && rm -Rf *
。 这意味着你将不得不调用escapeshellcmd
或escapeshellarg
。 这两种产品将不允许我通过一个有效的论据,是:
`mysql_config --libs --cflags`
其中含有反单引号,因此将被转义。
坦率地说,我很难看到这个练习的点...,我留下了很多了,还是:编译的危险 (更不用说运行)用户提供您的机器上的代码,例如,是不是被忽视。 你不能只是编译代码,并在服务器上运行它:内存泄露,内存设计缺陷......哎呀,纯粹的邪恶的代码是所有让你的服务器上选中编译如果这是你的代码。 真的,节省大量的眼泪,包括加载键盘或类似服务的iframe ...
概括:
- 经常检查男方的功能,看看你得到它返回的所有信息
- 检查实际被执行的命令的用户的权限和运行时
- 永远不要相信网络上,不要盲目地认为人们会提交有效,无害的代码可以编译。
- 不要重新发明轮子:编译服务存在的,只是转发的(但要求准予第一)
试试这个代码从PHP文件执行C程序
<?php
// used to compile the c file using exec() in php
exec('gcc helloworld.c -o helloworld', $out, $status);
if (0 === $status) {
var_dump($out);
// used to execute the c file using exec() in php
exec('./helloworld', $out, $status);
if (0 === $status) {
var_dump($out);
} else {
echo "Command failed with status: $status";
}
} else {
echo "Command failed with status: $status";
}
?>