46
46
#include <fcntl.h>
47
47
#endif
48
48
49
- #if HAVE_NICE && HAVE_UNISTD_H
49
+ #if HAVE_UNISTD_H
50
50
#include <unistd.h>
51
51
#endif
52
52
53
+ #ifdef PHP_WIN32
54
+ # include "win32/php_stdint.h"
55
+ #else
56
+ # if HAVE_INTTYPES_H
57
+ # include <inttypes.h>
58
+ # elif HAVE_STDINT_H
59
+ # include <stdint.h>
60
+ # endif
61
+ #endif
62
+
63
+ static int cmd_max_len ;
64
+
65
+ /* {{{ PHP_MINIT_FUNCTION(exec) */
66
+ PHP_MINIT_FUNCTION (exec )
67
+ {
68
+ #ifdef _SC_ARG_MAX
69
+ cmd_max_len = sysconf (_SC_ARG_MAX );
70
+ #elif defined(ARG_MAX )
71
+ cmd_max_len = ARG_MAX ;
72
+ #elif defined(PHP_WIN32 )
73
+ /* Executed commands will run through cmd.exe. As long as it's the case,
74
+ it's just the constant limit.*/
75
+ cmd_max_len = 8192 ;
76
+ #else
77
+ /* This is just an arbitrary value for the fallback case. */
78
+ cmd_max_len = 4096 ;
79
+ #endif
80
+
81
+ return SUCCESS ;
82
+ }
83
+ /* }}} */
84
+
53
85
/* {{{ php_exec
54
86
* If type==0, only last line of output is returned (exec)
55
87
* If type==1, all lines will be printed and last lined returned (system)
@@ -244,13 +276,20 @@ PHP_FUNCTION(passthru)
244
276
*/
245
277
PHPAPI char * php_escape_shell_cmd (char * str )
246
278
{
247
- register int x , y , l = strlen (str );
279
+ register int x , y ;
280
+ size_t l = strlen (str );
281
+ uint64_t estimate = (2 * (uint64_t )l ) + 1 ;
248
282
char * cmd ;
249
283
char * p = NULL ;
250
- size_t estimate = (2 * l ) + 1 ;
251
284
252
285
TSRMLS_FETCH ();
253
286
287
+ /* max command line length - two single quotes - \0 byte length */
288
+ if (l > cmd_max_len - 2 - 1 ) {
289
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Command exceeds the allowed length of %d bytes" , cmd_max_len );
290
+ return NULL ;
291
+ }
292
+
254
293
cmd = safe_emalloc (2 , l , 1 );
255
294
256
295
for (x = 0 , y = 0 ; x < l ; x ++ ) {
@@ -322,6 +361,12 @@ PHPAPI char *php_escape_shell_cmd(char *str)
322
361
}
323
362
cmd [y ] = '\0' ;
324
363
364
+ if (y - 1 > cmd_max_len ) {
365
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Escaped command exceeds the allowed length of %d bytes" , cmd_max_len );
366
+ efree (cmd );
367
+ return NULL ;
368
+ }
369
+
325
370
if ((estimate - y ) > 4096 ) {
326
371
/* realloc if the estimate was way overill
327
372
* Arbitrary cutoff point of 4096 */
@@ -336,12 +381,19 @@ PHPAPI char *php_escape_shell_cmd(char *str)
336
381
*/
337
382
PHPAPI char * php_escape_shell_arg (char * str )
338
383
{
339
- int x , y = 0 , l = strlen (str );
384
+ int x , y = 0 ;
385
+ size_t l = strlen (str );
340
386
char * cmd ;
341
- size_t estimate = (4 * l ) + 3 ;
387
+ uint64_t estimate = (4 * ( uint64_t ) l ) + 3 ;
342
388
343
389
TSRMLS_FETCH ();
344
390
391
+ /* max command line length - two single quotes - \0 byte length */
392
+ if (l > cmd_max_len - 2 - 1 ) {
393
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Argument exceeds the allowed length of %d bytes" , cmd_max_len );
394
+ return NULL ;
395
+ }
396
+
345
397
cmd = safe_emalloc (4 , l , 3 ); /* worst case */
346
398
347
399
#ifdef PHP_WIN32
@@ -396,6 +448,12 @@ PHPAPI char *php_escape_shell_arg(char *str)
396
448
#endif
397
449
cmd [y ] = '\0' ;
398
450
451
+ if (y - 1 > cmd_max_len ) {
452
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Escaped argument exceeds the allowed length of %d bytes" , cmd_max_len );
453
+ efree (cmd );
454
+ return NULL ;
455
+ }
456
+
399
457
if ((estimate - y ) > 4096 ) {
400
458
/* realloc if the estimate was way overill
401
459
* Arbitrary cutoff point of 4096 */
@@ -418,6 +476,10 @@ PHP_FUNCTION(escapeshellcmd)
418
476
}
419
477
420
478
if (command_len ) {
479
+ if (command_len != strlen (command )) {
480
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Input string contains NULL bytes" );
481
+ return ;
482
+ }
421
483
cmd = php_escape_shell_cmd (command );
422
484
RETVAL_STRING (cmd , 0 );
423
485
} else {
@@ -439,6 +501,10 @@ PHP_FUNCTION(escapeshellarg)
439
501
}
440
502
441
503
if (argument ) {
504
+ if (argument_len != strlen (argument )) {
505
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "Input string contains NULL bytes" );
506
+ return ;
507
+ }
442
508
cmd = php_escape_shell_arg (argument );
443
509
RETVAL_STRING (cmd , 0 );
444
510
}
0 commit comments