From 11a8ea96114c3120aa9ae8d60689f1b4caf6e572 Mon Sep 17 00:00:00 2001
From: Darian Anthony Patrick <dpatrick@wikimedia.org>
Date: Tue, 19 Apr 2016 10:53:39 -0700
Subject: [PATCH] Enforce upper limit on invocations of wfShellExec()

Enforce an upper limit of 100,000 bytes on commands executed via
wfShellExec() to avoid HHVM crash resulting from process spawned with
argument exceeding MAX_ARG_STRLEN, as defined in binfmts.h

Bug: T129506
---
 includes/Defines.php         | 6 ++++++
 includes/GlobalFunctions.php | 9 ++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/includes/Defines.php b/includes/Defines.php
index 9a6950e..19a08ef 100644
--- a/includes/Defines.php
+++ b/includes/Defines.php
@@ -305,3 +305,9 @@ define( 'CONTENT_FORMAT_JSON', 'application/json' );
 // for future use with the api, and for use by extensions
 define( 'CONTENT_FORMAT_XML', 'application/xml' );
 /**@}*/
+
+/**@{
+ * Max string length for shell invocations; based on binfmts.h
+ */
+define( 'SHELL_MAX_ARG_STRLEN', '100000');
+/**@}*/
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index 5c42bc2..af633ea 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -30,7 +30,6 @@ use MediaWiki\Session\SessionManager;
 
 // Hide compatibility functions from Doxygen
 /// @cond
-
 /**
  * Compatibility functions
  *
@@ -2425,6 +2424,14 @@ 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' ],
-- 
2.5.4 (Apple Git-61)

