Skip to content

Commit

Permalink
Coerce non-strings to strings in html() and regex(). [Fixes #2530408]
Browse files Browse the repository at this point in the history
  • Loading branch information
rgrove committed Jun 27, 2011
1 parent 2f33e4a commit 51eb59b
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 96 deletions.
14 changes: 14 additions & 0 deletions src/escape/HISTORY.md
Original file line number Diff line number Diff line change
@@ -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.
8 changes: 0 additions & 8 deletions src/escape/README → src/escape/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,3 @@ Escape
======

Provides utility methods for escaping strings.


Change History
--------------

3.3.0

* Initial release.
32 changes: 0 additions & 32 deletions src/escape/docs.sh

This file was deleted.

82 changes: 42 additions & 40 deletions src/escape/js/escape.js
Original file line number Diff line number Diff line change
@@ -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 = {
'&': '&',
Expand All @@ -21,44 +21,46 @@ Escape = {
// -- Public Static Methods ------------------------------------------------

/**
* <p>
* Returns a copy of the specified string with special HTML characters
* escaped. The following characters will be converted to their
* corresponding character entities:
* <code>&amp; &lt; &gt; &quot; &#x27; &#x2F; &#x60;</code>
* </p>
*
* <p>
* This implementation is based on the
* <a href="http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet">OWASP
* HTML escaping recommendations</a>. In addition to the characters
* in the OWASP recommendation, we also escape the <code>&#x60;</code>
* character, since IE interprets it as an attribute delimiter when used in
* innerHTML.
* </p>
*
* @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 <code>&#x60;</code> 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:
* <code>- # $ ^ * ( ) + [ ] { } | \ , . ?</code>
*
* @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 ---------------------------------------------
Expand Down
47 changes: 31 additions & 16 deletions src/escape/tests/functional/escape-test.js
Original file line number Diff line number Diff line change
@@ -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('&amp;&lt;&gt;&quot;&#x27;&#x2F;&#x60;', Escape.html('&<>"\'/`'));
Y.Assert.areSame('&amp;&amp;&amp;', Escape.html('&&&'));
Y.Assert.areSame('&lt;&lt;&lt;', Escape.html('<<<'));
Y.Assert.areSame('&gt;&gt;&gt;', Escape.html('>>>'));
Y.Assert.areSame('&quot;&quot;&quot;', Escape.html('"""'));
Y.Assert.areSame('&#x27;&#x27;&#x27;', Escape.html("'''"));
Y.Assert.areSame('&#x2F;&#x2F;&#x2F;', Escape.html("///"));
Y.Assert.areSame('&#x60;&#x60;&#x60;', Escape.html('```'));
Y.Assert.areSame('foo', Escape.html('foo'));
Y.Assert.areSame('foo &amp; bar', Escape.html('foo & bar'));
Assert.areSame('&amp;&lt;&gt;&quot;&#x27;&#x2F;&#x60;', Escape.html('&<>"\'/`'));
Assert.areSame('&amp;&amp;&amp;', Escape.html('&&&'));
Assert.areSame('&lt;&lt;&lt;', Escape.html('<<<'));
Assert.areSame('&gt;&gt;&gt;', Escape.html('>>>'));
Assert.areSame('&quot;&quot;&quot;', Escape.html('"""'));
Assert.areSame('&#x27;&#x27;&#x27;', Escape.html("'''"));
Assert.areSame('&#x2F;&#x2F;&#x2F;', Escape.html("///"));
Assert.areSame('&#x60;&#x60;&#x60;', Escape.html('```'));
Assert.areSame('foo', Escape.html('foo'));
Assert.areSame('foo &amp; 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);
}
}));

Expand Down

0 comments on commit 51eb59b

Please sign in to comment.