r95381 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r95380‎ | r95381 | r95382 >
Date:06:52, 24 August 2011
Author:tstarling
Status:deferred
Tags:
Comment:
* Did some minimal changes to make this extension work with my new PHP extension called luasandbox. The environment is not quite identical.
* Set configuration global variable defaults unconditionally, in line with the usual MediaWiki convention, to avoid register_globals vulnerabilities.
* Fixed a reference/value conflict in renderTag() which caused it to not work at all with recent versions of PHP.
* In renderTag(), put some more things inside the try block since even the constructor can throw exceptions.
Modified paths:
  • /trunk/extensions/Lua/Lua.hooks.php (modified) (history)
  • /trunk/extensions/Lua/Lua.php (modified) (history)
  • /trunk/extensions/Lua/Lua.wrapper.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Lua/Lua.wrapper.php
@@ -31,13 +31,14 @@
3232 */
3333 class LuaWrapper {
3434 private $defunct, $lua, $proc, $pipes;
 35+ private $sandbox, $out;
3536
3637 /**
3738 * Creates a new LuaWrapper.
3839 */
3940 public function __construct() {
4041 global $wgLuaMaxLines, $wgLuaMaxCalls,
41 - $wgLuaExternalInterpreter, $wgLuaExternalCompiler;
 42+ $wgLuaExternalInterpreter, $wgLuaExternalCompiler, $wgLuaExtension;
4243
4344 # Optionally byte-compile the wrapper library
4445 $wrapperLib = dirname(__FILE__) . '/LuaWrapper.lua';
@@ -56,7 +57,28 @@
5758 }
5859
5960 # Are we using the Lua PHP extension or an external binary?
60 - if (!$wgLuaExternalInterpreter) {
 61+ if ($wgLuaExternalInterpreter) {
 62+ # We're using an external binary; run the wrapper
 63+ # library as a shell-script, and it'll start an REPL
 64+ $luacmd = "$wgLuaExternalInterpreter $wrapperLib $wgLuaMaxLines $wgLuaMaxCalls";
 65+ # Create a new process and configure pipes to it
 66+ $this->proc = proc_open($luacmd,
 67+ array(0 => array('pipe', 'r'),
 68+ 1 => array('pipe', 'w')),
 69+ $this->pipes, null, null);
 70+ if (!is_resource($this->proc)) {
 71+ $this->defunct = TRUE;
 72+ throw new LuaError('interp_notfound');
 73+ }
 74+ stream_set_blocking($this->pipes[0], 0);
 75+ stream_set_blocking($this->pipes[1], 0);
 76+ stream_set_write_buffer($this->pipes[0], 0);
 77+ stream_set_write_buffer($this->pipes[1], 0);
 78+
 79+ # Ready to go.
 80+ $this->defunct = FALSE;
 81+ return TRUE;
 82+ } elseif ( $wgLuaExtension === 'lua' ) {
6183 # We're using the extension - verify it exists
6284 if (!class_exists('lua')) {
6385 $this->defunct = TRUE;
@@ -76,27 +98,17 @@
7799 # Ready to go.
78100 $this->defunct = FALSE;
79101 return TRUE;
80 - } else {
81 - # We're using an external binary; run the wrapper
82 - # library as a shell-script, and it'll start an REPL
83 - $luacmd = "$wgLuaExternalInterpreter $wrapperLib $wgLuaMaxLines $wgLuaMaxCalls";
84 - # Create a new process and configure pipes to it
85 - $this->proc = proc_open($luacmd,
86 - array(0 => array('pipe', 'r'),
87 - 1 => array('pipe', 'w')),
88 - $this->pipes, null, null);
89 - if (!is_resource($this->proc)) {
 102+ } elseif ( $wgLuaExtension === 'luasandbox' ) {
 103+ if (!class_exists('luasandbox')) {
90104 $this->defunct = TRUE;
91 - throw new LuaError('interp_notfound');
 105+ throw new LuaError( 'extension_notfound' );
92106 }
93 - stream_set_blocking($this->pipes[0], 0);
94 - stream_set_blocking($this->pipes[1], 0);
95 - stream_set_write_buffer($this->pipes[0], 0);
96 - stream_set_write_buffer($this->pipes[1], 0);
97107
98 - # Ready to go.
99 - $this->defunct = FALSE;
100 - return TRUE;
 108+ $this->sandbox = new LuaSandbox;
 109+ $this->sandbox->registerLibrary( 'mw', array( 'print' => array( $this, 'luaPrint' ) ) );
 110+ $this->sandbox->loadString( 'print = mw.print; io = {write = mw.print}' )->call();
 111+ } else {
 112+ throw new MWException( 'Invalid value for $wgLuaExtension' );
101113 }
102114 }
103115
@@ -133,6 +145,16 @@
134146 $res = $this->lua->wrap($input);
135147 $out = $res[0];
136148 $err = $res[1];
 149+ } elseif ( isset( $this->sandbox ) ) {
 150+ $err = '';
 151+ $out = '';
 152+ try {
 153+ $this->out = '';
 154+ $this->sandbox->loadString( $input )->call();
 155+ $out = $this->out;
 156+ } catch ( LuaSandboxError $e ) {
 157+ $err = $e->getMessage();
 158+ }
137159 } else {
138160 # We're using an external binary; send the chunk
139161 # through the pipe
@@ -198,7 +220,9 @@
199221 return FALSE;
200222
201223 # Destroy the lua instance and/or external process and pipes
202 - if (isset($this->lua)) {
 224+ if ( isset( $this->sandbox ) ) {
 225+ $this->sandbox = null;
 226+ } elseif (isset($this->lua)) {
203227 $this->lua = null;
204228 } else {
205229 if (isset($this->proc)) {
@@ -212,4 +236,19 @@
213237 $this->defunct = TRUE;
214238 return TRUE;
215239 }
 240+
 241+ public function luaPrint() {
 242+ $args = func_get_args();
 243+ foreach ( $args as $i => $arg ) {
 244+ if ( $i >= 1 ) {
 245+ $this->out .= "\t";
 246+ }
 247+ if ( $arg instanceof LuaSandboxPlaceholder ) {
 248+ $this->out .= "[placeholder]";
 249+ } else {
 250+ $this->out .= $arg;
 251+ }
 252+ }
 253+ }
 254+
216255 }
Index: trunk/extensions/Lua/Lua.php
@@ -22,16 +22,12 @@
2323 $wgAutoloadClasses['LuaError'] = $dir . 'Lua.wrapper.php';
2424 $wgAutoloadClasses['LuaWrapper'] = $dir . 'Lua.wrapper.php';
2525
26 -if (!isset($wgLuaExternalInterpreter))
27 - $wgLuaExternalInterpreter = FALSE;
28 -if (!isset($wgLuaExternalCompiler))
29 - $wgLuaExternalCompiler = FALSE;
30 -if (!isset($wgLuaMaxLines))
31 - $wgLuaMaxLines = 1000000;
32 -if (!isset($wgLuaMaxCalls))
33 - $wgLuaMaxCalls = 2000;
34 -if (!isset($wgLuaMaxTime))
35 - $wgLuaMaxTime = 5;
 26+$wgLuaExternalInterpreter = FALSE;
 27+$wgLuaExternalCompiler = FALSE;
 28+$wgLuaExtension = 'lua';
 29+$wgLuaMaxLines = 1000000;
 30+$wgLuaMaxCalls = 2000;
 31+$wgLuaMaxTime = 5;
3632
3733
3834 $wgHooks['ParserFirstCallInit'][] = 'LuaHooks::parserInit';
Index: trunk/extensions/Lua/Lua.hooks.php
@@ -32,30 +32,30 @@
3333 }
3434
3535 /** Parser hook for the <lua> tag */
36 - public static function renderTag($input, $args, &$parser) {
37 - global $wgLua;
38 - # Create a new LuaWrapper if needed
39 - if (!isset($wgLua))
40 - $wgLua = new LuaWrapper;
 36+ public static function renderTag($input, $args, $parser) {
 37+ try {
 38+ global $wgLua;
 39+ # Create a new LuaWrapper if needed
 40+ if (!isset($wgLua))
 41+ $wgLua = new LuaWrapper;
4142
42 - # Process the tag's arguments into a chunk of Lua code
43 - # that initializes them in the Lua sandbox
44 - $arglist = '';
45 - foreach ($args as $key => $value)
46 - $arglist .= (preg_replace('/\W/', '', $key) . '=\'' .
47 - addslashes($parser->recursiveTagParse($value)) .
48 - '\';');
49 - if ($arglist) {
50 - try {
51 - $wgLua->wrap($arglist);
52 - } catch (LuaError $e) {
53 - return $e->getMessage();
 43+ # Process the tag's arguments into a chunk of Lua code
 44+ # that initializes them in the Lua sandbox
 45+ $arglist = '';
 46+ foreach ($args as $key => $value)
 47+ $arglist .= (preg_replace('/\W/', '', $key) . '=\'' .
 48+ addslashes($parser->recursiveTagParse($value)) .
 49+ '\';');
 50+ if ($arglist) {
 51+ try {
 52+ $wgLua->wrap($arglist);
 53+ } catch (LuaError $e) {
 54+ return $e->getMessage();
 55+ }
5456 }
55 - }
5657
57 - # Execute this Lua chunk, and send the results through the
58 - # Parser.
59 - try {
 58+ # Execute this Lua chunk, and send the results through the
 59+ # Parser.
6060 return $parser->recursiveTagParse($wgLua->wrap($input));
6161 } catch (LuaError $e) {
6262 return $e->getMessage();

Status & tagging log