From 51eb59b098a3ad87376f1ac4d405799c7651a084 Mon Sep 17 00:00:00 2001 From: Ryan Grove Date: Mon, 27 Jun 2011 16:46:48 -0700 Subject: [PATCH] Coerce non-strings to strings in html() and regex(). [Fixes #2530408] --- src/escape/HISTORY.md | 14 ++++ src/escape/{README => README.md} | 8 --- src/escape/docs.sh | 32 --------- src/escape/js/escape.js | 82 +++++++++++----------- src/escape/tests/functional/escape-test.js | 47 ++++++++----- 5 files changed, 87 insertions(+), 96 deletions(-) create mode 100644 src/escape/HISTORY.md rename src/escape/{README => README.md} (50%) delete mode 100755 src/escape/docs.sh diff --git a/src/escape/HISTORY.md b/src/escape/HISTORY.md new file mode 100644 index 00000000000..aede92a062f --- /dev/null +++ b/src/escape/HISTORY.md @@ -0,0 +1,14 @@ +Escape Change History +===================== + +3.4.0 +----- + + * Non-string arguments to `html()` and `regex()` are now coerced to strings. + [Ticket #2530408] + + +3.3.0 +----- + + * Initial release. diff --git a/src/escape/README b/src/escape/README.md similarity index 50% rename from src/escape/README rename to src/escape/README.md index 0031156371e..eca816f839d 100644 --- a/src/escape/README +++ b/src/escape/README.md @@ -2,11 +2,3 @@ Escape ====== Provides utility methods for escaping strings. - - -Change History --------------- - -3.3.0 - - * Initial release. diff --git a/src/escape/docs.sh b/src/escape/docs.sh deleted file mode 100755 index 2c3f6788110..00000000000 --- a/src/escape/docs.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# The location of your yuidoc install -yuidoc_home=../../../yuidoc - -# The location of the files to parse. Parses subdirectories, but will fail if -# there are duplicate file names in these directories. You can specify multiple -# source trees: -# parser_in="%HOME/www/yui/src %HOME/www/event/src" -parser_in=js - -# The location to output the parser data. This output is a file containing a -# json string, and copies of the parsed files. -parser_out=build_api_parser - -# The directory to put the html file outputted by the generator -generator_out=build_api - -# The location of the template files. Any subdirectories here will be copied -# verbatim to the destination directory. -template=$yuidoc_home/template - -# The version of your project to display within the documentation. -version=1.0.0 - -# The version of YUI the project is using. This effects the output for -# YUI configuration attributes. This should start with '2' or '3'. -yuiversion=3 - -############################################################################## -# add -s to the end of the line to show items marked private - -$yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -Y $yuiversion diff --git a/src/escape/js/escape.js b/src/escape/js/escape.js index d4f8cc2e8ef..4163ed637a5 100644 --- a/src/escape/js/escape.js +++ b/src/escape/js/escape.js @@ -1,11 +1,11 @@ /** - * Provides utility methods for escaping strings. - * - * @module escape - * @class Escape - * @static - * @since 3.3.0 - */ +Provides utility methods for escaping strings. + +@module escape +@class Escape +@static +@since 3.3.0 +**/ var HTML_CHARS = { '&': '&', @@ -21,44 +21,46 @@ Escape = { // -- Public Static Methods ------------------------------------------------ /** - *

- * Returns a copy of the specified string with special HTML characters - * escaped. The following characters will be converted to their - * corresponding character entities: - * & < > " ' / ` - *

- * - *

- * This implementation is based on the - * OWASP - * HTML escaping recommendations. In addition to the characters - * in the OWASP recommendation, we also escape the ` - * character, since IE interprets it as an attribute delimiter when used in - * innerHTML. - *

- * - * @method html - * @param {String} string String to escape. - * @return {String} Escaped string. - * @static - */ + Returns a copy of the specified string with special HTML characters + escaped. The following characters will be converted to their + corresponding character entities: + + & < > " ' / ` + + This implementation is based on the [OWASP HTML escaping + recommendations][1]. In addition to the characters in the OWASP + recommendations, we also escape the ` character, since IE + interprets it as an attribute delimiter. + + If _string_ is not already a string, it will be coerced to a string. + + [1]: http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet + + @method html + @param {String} string String to escape. + @return {String} Escaped string. + @static + **/ html: function (string) { - return string.replace(/[&<>"'\/`]/g, Escape._htmlReplacer); + return (string + '').replace(/[&<>"'\/`]/g, Escape._htmlReplacer); }, /** - * Returns a copy of the specified string with special regular expression - * characters escaped, allowing the string to be used safely inside a regex. - * The following characters, and all whitespace characters, are escaped: - * - # $ ^ * ( ) + [ ] { } | \ , . ? - * - * @method regex - * @param {String} string String to escape. - * @return {String} Escaped string. - * @static - */ + Returns a copy of the specified string with special regular expression + characters escaped, allowing the string to be used safely inside a regex. + The following characters, and all whitespace characters, are escaped: + + - # $ ^ * ( ) + [ ] { } | \ , . ? + + If _string_ is not already a string, it will be coerced to a string. + + @method regex + @param {String} string String to escape. + @return {String} Escaped string. + @static + **/ regex: function (string) { - return string.replace(/[\-#$\^*()+\[\]{}|\\,.?\s]/g, '\\$&'); + return (string + '').replace(/[\-#$\^*()+\[\]{}|\\,.?\s]/g, '\\$&'); }, // -- Protected Static Methods --------------------------------------------- diff --git a/src/escape/tests/functional/escape-test.js b/src/escape/tests/functional/escape-test.js index 0086fb6ad3e..d607cdcbbf3 100644 --- a/src/escape/tests/functional/escape-test.js +++ b/src/escape/tests/functional/escape-test.js @@ -1,32 +1,47 @@ YUI.add('escape-test', function (Y) { -var Escape = Y.Escape; +var Assert = Y.Assert, + Escape = Y.Escape; Y.Test.Runner.add(new Y.Test.Case({ name: 'Escape', 'html() should escape HTML characters': function () { - Y.Assert.areSame('&<>"'/`', Escape.html('&<>"\'/`')); - Y.Assert.areSame('&&&', Escape.html('&&&')); - Y.Assert.areSame('<<<', Escape.html('<<<')); - Y.Assert.areSame('>>>', Escape.html('>>>')); - Y.Assert.areSame('"""', Escape.html('"""')); - Y.Assert.areSame(''''', Escape.html("'''")); - Y.Assert.areSame('///', Escape.html("///")); - Y.Assert.areSame('```', Escape.html('```')); - Y.Assert.areSame('foo', Escape.html('foo')); - Y.Assert.areSame('foo & bar', Escape.html('foo & bar')); + Assert.areSame('&<>"'/`', Escape.html('&<>"\'/`')); + Assert.areSame('&&&', Escape.html('&&&')); + Assert.areSame('<<<', Escape.html('<<<')); + Assert.areSame('>>>', Escape.html('>>>')); + Assert.areSame('"""', Escape.html('"""')); + Assert.areSame(''''', Escape.html("'''")); + Assert.areSame('///', Escape.html("///")); + Assert.areSame('```', Escape.html('```')); + Assert.areSame('foo', Escape.html('foo')); + Assert.areSame('foo & bar', Escape.html('foo & bar')); + }, + + 'html() should coerce non-strings to strings': function () { + Assert.areSame('1', Escape.html(1)); + Assert.areSame('false', Escape.html(false)); + Assert.areSame('null', Escape.html(null)); + Assert.areSame('undefined', Escape.html()); }, 'regex() should escape regular expression characters': function () { - Y.Assert.areSame('\\-\\#\\$\\^\\*\\(\\)\\+\\[\\]\\{\\}\\|\\\\\\\,\\.\\?\\ \\\t', Escape.regex('-#$^*()+[]{}|\\,.? \t')); - Y.Assert.areSame('\\*\\*\\*', Escape.regex('***')); - Y.Assert.areSame('foo', Escape.regex('foo')); - Y.Assert.areSame('foo\\-bar', Escape.regex('foo-bar')); + Assert.areSame('\\-\\#\\$\\^\\*\\(\\)\\+\\[\\]\\{\\}\\|\\\\\\\,\\.\\?\\ \\\t', Escape.regex('-#$^*()+[]{}|\\,.? \t')); + Assert.areSame('\\*\\*\\*', Escape.regex('***')); + Assert.areSame('foo', Escape.regex('foo')); + Assert.areSame('foo\\-bar', Escape.regex('foo-bar')); + }, + + 'regex() should coerce non-strings to strings': function () { + Assert.areSame('1', Escape.regex(1)); + Assert.areSame('false', Escape.regex(false)); + Assert.areSame('null', Escape.regex(null)); + Assert.areSame('undefined', Escape.regex()); }, 'regexp() should be an alias for regex()': function () { - Y.Assert.areSame(Escape.regex, Escape.regexp); + Assert.areSame(Escape.regex, Escape.regexp); } }));