From 6c803340da09bc9425085b9c9c3204346d22d81a Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Mon, 14 Mar 2016 11:48:20 -0400 Subject: [PATCH] SECURITY: Don't escape strip markers when escaping attributes in mw.html Core strip markers were changed in T110143 to include characters that are normally encoded in attributes, however we want to pass them through here so they can be unstripped correctly in the output wikitext. This fix makes "Strip markers in CSS" parser test pass again. Change-Id: I1353931a53c668d8a453dfa2300a99f59fdb01c5 --- engines/LuaCommon/HtmlLibrary.php | 5 +++- engines/LuaCommon/lualib/mw.html.lua | 34 +++++++++++++++++++++------- tests/engines/LuaCommon/HtmlLibraryTest.php | 14 ++++++++++++ tests/engines/LuaCommon/HtmlLibraryTests.lua | 12 ++++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/engines/LuaCommon/HtmlLibrary.php b/engines/LuaCommon/HtmlLibrary.php index 5b413d8..1cbf63e 100644 --- a/engines/LuaCommon/HtmlLibrary.php +++ b/engines/LuaCommon/HtmlLibrary.php @@ -2,6 +2,9 @@ class Scribunto_LuaHtmlLibrary extends Scribunto_LuaLibraryBase { function register() { - return $this->getEngine()->registerInterface( 'mw.html.lua', array() ); + return $this->getEngine()->registerInterface( 'mw.html.lua', array(), array( + 'uniqPrefix' => Parser::MARKER_PREFIX, + 'uniqSuffix' => Parser::MARKER_SUFFIX, + ) ); } } diff --git a/engines/LuaCommon/lualib/mw.html.lua b/engines/LuaCommon/lualib/mw.html.lua index 7411de5..2e58e98 100644 --- a/engines/LuaCommon/lualib/mw.html.lua +++ b/engines/LuaCommon/lualib/mw.html.lua @@ -14,6 +14,7 @@ ]] local HtmlBuilder = {} +local options local util = require 'libraryUtil' local checkType = util.checkType @@ -87,7 +88,11 @@ end -- @param s local function htmlEncode( s ) -- The parentheses ensure that there is only one return value - return ( string.gsub( s, '[<>&"]', htmlencodeMap ) ) + local tmp = string.gsub( s, '[<>&"]', htmlencodeMap ); + -- Don't encode strip markers here (T110143) + tmp = string.gsub( tmp, options.encodedUniqPrefixPat, options.uniqPrefixRepl ) + tmp = string.gsub( tmp, options.encodedUniqSuffixPat, options.uniqSuffixRepl ) + return tmp end local function cssEncode( s ) @@ -401,12 +406,25 @@ function HtmlBuilder.create( tagName, args ) return createBuilder( tagName, args ) end -mw_interface = nil - --- Register this library in the "mw" global -mw = mw or {} -mw.html = HtmlBuilder - -package.loaded['mw.html'] = HtmlBuilder +function HtmlBuilder.setupInterface( opts ) + -- Boilerplate + HtmlBuilder.setupInterface = nil + mw_interface = nil + options = opts + + -- Prepare patterns for unencoding strip markers + options.encodedUniqPrefixPat = string.gsub( options.uniqPrefix, '[<>&"]', htmlencodeMap ); + options.encodedUniqPrefixPat = string.gsub( options.encodedUniqPrefixPat, '%p', '%%%0' ); + options.uniqPrefixRepl = string.gsub( options.uniqPrefix, '%%', '%%%0' ); + options.encodedUniqSuffixPat = string.gsub( options.uniqSuffix, '[<>&"]', htmlencodeMap ); + options.encodedUniqSuffixPat = string.gsub( options.encodedUniqSuffixPat, '%p', '%%%0' ); + options.uniqSuffixRepl = string.gsub( options.uniqSuffix, '%%', '%%%0' ); + + -- Register this library in the "mw" global + mw = mw or {} + mw.html = HtmlBuilder + + package.loaded['mw.html'] = HtmlBuilder +end return HtmlBuilder diff --git a/tests/engines/LuaCommon/HtmlLibraryTest.php b/tests/engines/LuaCommon/HtmlLibraryTest.php index 5b47962..1f74a9f 100644 --- a/tests/engines/LuaCommon/HtmlLibraryTest.php +++ b/tests/engines/LuaCommon/HtmlLibraryTest.php @@ -3,6 +3,20 @@ class Scribunto_LuaHtmlLibraryTests extends Scribunto_LuaEngineTestBase { protected static $moduleName = 'HtmlLibraryTests'; + protected function setUp() { + parent::setUp(); + + // For strip marker test + $markers = array( + 'nowiki' => Parser::MARKER_PREFIX . '-test-nowiki-' . Parser::MARKER_SUFFIX, + ); + $interpreter = $this->getEngine()->getInterpreter(); + $interpreter->callFunction( + $interpreter->loadString( 'mw.html.stripMarkers = ...', 'fortest' ), + $markers + ); + } + protected function getTestModules() { return parent::getTestModules() + array( 'HtmlLibraryTests' => __DIR__ . '/HtmlLibraryTests.lua', diff --git a/tests/engines/LuaCommon/HtmlLibraryTests.lua b/tests/engines/LuaCommon/HtmlLibraryTests.lua index f7ebfaf..e9ea123 100644 --- a/tests/engines/LuaCommon/HtmlLibraryTests.lua +++ b/tests/engines/LuaCommon/HtmlLibraryTests.lua @@ -101,6 +101,15 @@ local function testComplex() return builder end +local function testStripMarker() + local expect = '
' + local actual = tostring( getEmptyTestDiv():attr( 'foo', mw.html.stripMarkers.nowiki ) ) + if actual ~= expect then + error( actual .. ' ~= ' .. expect ) + end + return 'ok' +end + -- Tests local tests = { -- Simple (inline) tests @@ -342,6 +351,9 @@ local tests = { '
' } }, + { name = 'mw.html strip marker test', func = testStripMarker, type='ToString', + expect = { 'ok' } + }, } return testframework.getTestProvider( tests ) -- 2.6.6