Merge "mw.widgets.CategorySelector: Avoid JS exceptions for invalid user input"
[lhc/web/wiklou.git] / includes / GlobalFunctions.php
index 537bdef..66e2440 100644 (file)
@@ -30,7 +30,6 @@ use MediaWiki\Session\SessionManager;
 
 // Hide compatibility functions from Doxygen
 /// @cond
-
 /**
  * Compatibility functions
  *
@@ -2134,6 +2133,24 @@ function wfTempDir() {
                        return $tmp;
                }
        }
+
+       /**
+        * PHP on Windows will detect C:\Windows\Temp as not writable even though PHP can write to it
+        * so create a directory within that called 'mwtmp' with a suffix of the user running the
+        * current process.
+        * The user is included as if various scripts are run by different users they will likely
+        * not be able to access each others temporary files.
+        */
+       if ( wfIsWindows() ) {
+               $tmp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mwtmp' . '-' . get_current_user();
+               if ( !file_exists( $tmp ) ) {
+                       mkdir( $tmp );
+               }
+               if ( file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
+                       return $tmp;
+               }
+       }
+
        throw new MWException( 'No writable temporary directory could be found. ' .
                'Please set $wgTmpDirectory to a writable directory.' );
 }
@@ -2439,6 +2456,15 @@ function wfShellExec( $cmd, &$retval = null, $environ = [],
        }
        wfDebug( "wfShellExec: $cmd\n" );
 
+       // Don't try to execute commands that exceed Linux's MAX_ARG_STRLEN.
+       // Other platforms may be more accomodating, but we don't want to be
+       // accomodating, because very long commands probably include user
+       // input. See T129506.
+       if ( strlen( $cmd ) > SHELL_MAX_ARG_STRLEN ) {
+               throw new Exception( __METHOD__ .
+                       '(): total length of $cmd must not exceed SHELL_MAX_ARG_STRLEN' );
+       }
+
        $desc = [
                0 => [ 'file', 'php://stdin', 'r' ],
                1 => [ 'pipe', 'w' ],
@@ -2473,14 +2499,6 @@ function wfShellExec( $cmd, &$retval = null, $environ = [],
        $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
        $eintrMessage = "stream_select(): unable to select [$eintr]";
 
-       // Build a table mapping resource IDs to pipe FDs to work around a
-       // PHP 5.3 issue in which stream_select() does not preserve array keys
-       // <https://bugs.php.net/bug.php?id=53427>.
-       $fds = [];
-       foreach ( $pipes as $fd => $pipe ) {
-               $fds[(int)$pipe] = $fd;
-       }
-
        $running = true;
        $timeout = null;
        $numReadyPipes = 0;
@@ -2513,9 +2531,8 @@ function wfShellExec( $cmd, &$retval = null, $environ = [],
                                break;
                        }
                }
-               foreach ( $readyPipes as $pipe ) {
+               foreach ( $readyPipes as $fd => $pipe ) {
                        $block = fread( $pipe, 65536 );
-                       $fd = $fds[(int)$pipe];
                        if ( $block === '' ) {
                                // End of file
                                fclose( $pipes[$fd] );