From: Tim Starling Date: Wed, 8 Feb 2012 00:03:16 +0000 (+0000) Subject: Revert r110321: introduces an XSS vulnerability because FormatJson::encode() does... X-Git-Tag: 1.31.0-rc.0~24881 X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=8a9b79dda736e1db568f8d743c999ec956d704e7;p=lhc%2Fweb%2Fwiklou.git Revert r110321: introduces an XSS vulnerability because FormatJson::encode() does not prevent the termination of CDATA sections when JavaScript is embedded in HTML. --- diff --git a/includes/Xml.php b/includes/Xml.php index f866ff0bd5..7e5b3cdba9 100644 --- a/includes/Xml.php +++ b/includes/Xml.php @@ -607,19 +607,52 @@ class Xml { } /** - * Encode a variable of unknown type to JavaScript. If you're not dealing - * with potential instances of XmlJsCode (which bypass encoding), then - * FormatJson::encode should be used directly. + * Encode a variable of unknown type to JavaScript. + * Arrays are converted to JS arrays, objects are converted to JS associative + * arrays (objects). So cast your PHP associative arrays to objects before + * passing them to here. * * @param $value * * @return string */ public static function encodeJsVar( $value ) { - if ( $value instanceof XmlJsCode ) { - return $value->value; + if ( is_bool( $value ) ) { + $s = $value ? 'true' : 'false'; + } elseif ( is_null( $value ) ) { + $s = 'null'; + } elseif ( is_int( $value ) || is_float( $value ) ) { + $s = strval($value); + } elseif ( is_array( $value ) && // Make sure it's not associative. + array_keys($value) === range( 0, count($value) - 1 ) || + count($value) == 0 + ) { + $s = '['; + foreach ( $value as $elt ) { + if ( $s != '[' ) { + $s .= ','; + } + $s .= self::encodeJsVar( $elt ); + } + $s .= ']'; + } elseif ( $value instanceof XmlJsCode ) { + $s = $value->value; + } elseif ( is_object( $value ) || is_array( $value ) ) { + // Objects and associative arrays + $s = '{'; + foreach ( (array)$value as $name => $elt ) { + if ( $s != '{' ) { + $s .= ','; + } + + $s .= '"' . self::escapeJsString( $name ) . '":' . + self::encodeJsVar( $elt ); + } + $s .= '}'; + } else { + $s = '"' . self::escapeJsString( $value ) . '"'; } - return FormatJson::encode( $value ); + return $s; } /**