mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
backport the escapeshell* functions hardening branch
This commit is contained in:
parent
828364e59c
commit
f4d7bbf4ac
@ -3674,6 +3674,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
|
||||
#ifdef PHP_CAN_SUPPORT_PROC_OPEN
|
||||
BASIC_MINIT_SUBMODULE(proc_open)
|
||||
#endif
|
||||
BASIC_MINIT_SUBMODULE(exec)
|
||||
|
||||
BASIC_MINIT_SUBMODULE(user_streams)
|
||||
BASIC_MINIT_SUBMODULE(imagetypes)
|
||||
|
@ -46,10 +46,42 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NICE && HAVE_UNISTD_H
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# include "win32/php_stdint.h"
|
||||
#else
|
||||
# if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
# elif HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static int cmd_max_len;
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION(exec) */
|
||||
PHP_MINIT_FUNCTION(exec)
|
||||
{
|
||||
#ifdef _SC_ARG_MAX
|
||||
cmd_max_len = sysconf(_SC_ARG_MAX);
|
||||
#elif defined(ARG_MAX)
|
||||
cmd_max_len = ARG_MAX;
|
||||
#elif defined(PHP_WIN32)
|
||||
/* Executed commands will run through cmd.exe. As long as it's the case,
|
||||
it's just the constant limit.*/
|
||||
cmd_max_len = 8192;
|
||||
#else
|
||||
/* This is just an arbitrary value for the fallback case. */
|
||||
cmd_max_len = 4096;
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_exec
|
||||
* If type==0, only last line of output is returned (exec)
|
||||
* If type==1, all lines will be printed and last lined returned (system)
|
||||
@ -244,13 +276,20 @@ PHP_FUNCTION(passthru)
|
||||
*/
|
||||
PHPAPI char *php_escape_shell_cmd(char *str)
|
||||
{
|
||||
register int x, y, l = strlen(str);
|
||||
register int x, y;
|
||||
size_t l = strlen(str);
|
||||
uint64_t estimate = (2 * (uint64_t)l) + 1;
|
||||
char *cmd;
|
||||
char *p = NULL;
|
||||
size_t estimate = (2 * l) + 1;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* max command line length - two single quotes - \0 byte length */
|
||||
if (l > cmd_max_len - 2 - 1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Command exceeds the allowed length of %d bytes", cmd_max_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd = safe_emalloc(2, l, 1);
|
||||
|
||||
for (x = 0, y = 0; x < l; x++) {
|
||||
@ -322,6 +361,12 @@ PHPAPI char *php_escape_shell_cmd(char *str)
|
||||
}
|
||||
cmd[y] = '\0';
|
||||
|
||||
if (y - 1 > cmd_max_len) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Escaped command exceeds the allowed length of %d bytes", cmd_max_len);
|
||||
efree(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((estimate - y) > 4096) {
|
||||
/* realloc if the estimate was way overill
|
||||
* Arbitrary cutoff point of 4096 */
|
||||
@ -336,12 +381,19 @@ PHPAPI char *php_escape_shell_cmd(char *str)
|
||||
*/
|
||||
PHPAPI char *php_escape_shell_arg(char *str)
|
||||
{
|
||||
int x, y = 0, l = strlen(str);
|
||||
int x, y = 0;
|
||||
size_t l = strlen(str);
|
||||
char *cmd;
|
||||
size_t estimate = (4 * l) + 3;
|
||||
uint64_t estimate = (4 * (uint64_t)l) + 3;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* max command line length - two single quotes - \0 byte length */
|
||||
if (l > cmd_max_len - 2 - 1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Argument exceeds the allowed length of %d bytes", cmd_max_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd = safe_emalloc(4, l, 3); /* worst case */
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
@ -396,6 +448,12 @@ PHPAPI char *php_escape_shell_arg(char *str)
|
||||
#endif
|
||||
cmd[y] = '\0';
|
||||
|
||||
if (y - 1 > cmd_max_len) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Escaped argument exceeds the allowed length of %d bytes", cmd_max_len);
|
||||
efree(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((estimate - y) > 4096) {
|
||||
/* realloc if the estimate was way overill
|
||||
* Arbitrary cutoff point of 4096 */
|
||||
@ -418,6 +476,10 @@ PHP_FUNCTION(escapeshellcmd)
|
||||
}
|
||||
|
||||
if (command_len) {
|
||||
if (command_len != strlen(command)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Input string contains NULL bytes");
|
||||
return;
|
||||
}
|
||||
cmd = php_escape_shell_cmd(command);
|
||||
RETVAL_STRING(cmd, 0);
|
||||
} else {
|
||||
@ -439,6 +501,10 @@ PHP_FUNCTION(escapeshellarg)
|
||||
}
|
||||
|
||||
if (argument) {
|
||||
if (argument_len != strlen(argument)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Input string contains NULL bytes");
|
||||
return;
|
||||
}
|
||||
cmd = php_escape_shell_arg(argument);
|
||||
RETVAL_STRING(cmd, 0);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ PHP_FUNCTION(proc_close);
|
||||
PHP_FUNCTION(proc_terminate);
|
||||
PHP_FUNCTION(proc_nice);
|
||||
PHP_MINIT_FUNCTION(proc_open);
|
||||
PHP_MINIT_FUNCTION(exec);
|
||||
|
||||
PHPAPI char *php_escape_shell_cmd(char *);
|
||||
PHPAPI char *php_escape_shell_arg(char *);
|
||||
|
Loading…
Reference in New Issue
Block a user