From 2b49b3bde77e3fda0884885abe8ff7723f3dcaa6 Mon Sep 17 00:00:00 2001 From: David Lynch Date: Mon, 12 Dec 2022 09:37:30 -0600 Subject: [PATCH] Try/catch around mw.Uri when decoding parsoid resources An incorrectly-encoded fragment is allowed-in-wikitext but will make mw.Uri throw an error. e.g. `[[foo#1%bar]]` Bug: T324976 Change-Id: I97cb85507d9ae3d648300245dd7e48cc239c4d90 --- modules/ve-mw/preinit/ve.utils.parsoid.js | 49 ++++++++++++++--------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/modules/ve-mw/preinit/ve.utils.parsoid.js b/modules/ve-mw/preinit/ve.utils.parsoid.js index 8aa899c242..892dc354f4 100644 --- a/modules/ve-mw/preinit/ve.utils.parsoid.js +++ b/modules/ve-mw/preinit/ve.utils.parsoid.js @@ -288,30 +288,43 @@ mw.libs.ve.getTargetDataFromHref = function ( href, doc ) { if ( href.match( /^\.\// ) ) { // The specific case of parsoid resource URIs, which are in the form `./Title`. // If they're redlinks they now include a querystring which should be stripped. - uri = new mw.Uri( href ); - queryLength = Object.keys( uri.query ).length; - if ( - ( queryLength === 2 && uri.query.action === 'edit' && uri.query.redlink === '1' ) - ) { - uri.query = {}; - href = '.' + uri.getRelativePath(); + try { + uri = new mw.Uri( href ); + } catch ( e ) { + // probably an incorrecly encoded URI, try a very-naïve fallback + href = href.replace( /\?action=edit&redlink=1$/, '' ); + } + if ( uri ) { + queryLength = Object.keys( uri.query ).length; + if ( + ( queryLength === 2 && uri.query.action === 'edit' && uri.query.redlink === '1' ) + ) { + uri.query = {}; + href = '.' + uri.getRelativePath(); + } } } } else { // Check if this matches the server's script path (as used by red links) var scriptBase = mw.libs.ve.resolveUrl( mw.config.get( 'wgScript' ), doc ).replace( /^https?:/i, '' ); if ( relativeHref.indexOf( scriptBase ) === 0 ) { - uri = new mw.Uri( relativeHref ); - queryLength = Object.keys( uri.query ).length; - if ( - ( queryLength === 1 && uri.query.title ) || - ( queryLength === 3 && uri.query.title && uri.query.action === 'edit' && uri.query.redlink === '1' ) - ) { - href = uri.query.title + ( uri.fragment ? '#' + uri.fragment : '' ); - isInternal = true; - } else if ( queryLength > 1 ) { - href = relativeHref; - isInternal = false; + try { + uri = new mw.Uri( relativeHref ); + } catch ( e ) { + // probably an incorrectly encoded URI + } + if ( uri ) { + queryLength = Object.keys( uri.query ).length; + if ( + ( queryLength === 1 && uri.query.title ) || + ( queryLength === 3 && uri.query.title && uri.query.action === 'edit' && uri.query.redlink === '1' ) + ) { + href = uri.query.title + ( uri.fragment ? '#' + uri.fragment : '' ); + isInternal = true; + } else if ( queryLength > 1 ) { + href = relativeHref; + isInternal = false; + } } } if ( isInternal === null ) {