Skip to content

Commit

Permalink
Core: Make jQuery.fn.init more resilient
Browse files Browse the repository at this point in the history
Fixes #178
Closes #183

- Better sniff for a jQuery object, avoids document.context trap
- Don't do string checks on non-string arguments to init
  • Loading branch information
dmethvin committed Apr 29, 2016
1 parent a3eb7da commit c09b6a0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 35 deletions.
73 changes: 39 additions & 34 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,50 @@ var matched, browser,
jQuery.fn.init = function( selector, context, rootjQuery ) {
var match, ret;

if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
(match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {
// This is an HTML string according to the "old" rules; is it still?
if ( !rspaceAngle.test( selector ) ) {
migrateWarn("$(html) HTML strings must start with '<' character");
}
if ( match[ 3 ] ) {
migrateWarn("$(html) HTML text after last tag is ignored");
if ( selector && typeof selector === "string" ) {
if ( !jQuery.isPlainObject( context ) &&
(match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {

// This is an HTML string according to the "old" rules; is it still?
if ( !rspaceAngle.test( selector ) ) {
migrateWarn("$(html) HTML strings must start with '<' character");
}
if ( match[ 3 ] ) {
migrateWarn("$(html) HTML text after last tag is ignored");
}

// Consistently reject any HTML-like string starting with a hash (gh-9521)
// Note that this may break jQuery 1.6.x code that otherwise would work.
if ( match[ 0 ].charAt( 0 ) === "#" ) {
migrateWarn("HTML string cannot start with a '#' character");
jQuery.error("JQMIGRATE: Invalid selector string (XSS)");
}

// Now process using loose rules; let pre-1.8 play too
// Is this a jQuery context? parseHTML expects a DOM element (#178)
if ( context && context.context && context.context.nodeType ) {
context = context.context;
}

if ( jQuery.parseHTML ) {
return oldInit.call( this,
jQuery.parseHTML( match[ 2 ], context && context.ownerDocument ||
context || document, true ), context, rootjQuery );
}
}

// Consistently reject any HTML-like string starting with a hash (#9521)
// Note that this may break jQuery 1.6.x code that otherwise would work.
if ( match[ 0 ].charAt( 0 ) === "#" ) {
migrateWarn("HTML string cannot start with a '#' character");
jQuery.error("JQMIGRATE: Invalid selector string (XSS)");
}
// Now process using loose rules; let pre-1.8 play too
if ( context && context.context ) {
// jQuery object as context; parseHTML expects a DOM object
context = context.context;
}
if ( jQuery.parseHTML ) {
return oldInit.call( this,
jQuery.parseHTML( match[ 2 ], context && context.ownerDocument ||
context || document, true ), context, rootjQuery );
}
}

if ( selector === "#" ) {
if ( selector === "#" ) {

// jQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0
migrateWarn( "jQuery( '#' ) is not a valid selector" );
selector = [];
// jQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0
migrateWarn( "jQuery( '#' ) is not a valid selector" );
selector = [];

} else if ( rattrHash.test( selector ) ) {
} else if ( rattrHash.test( selector ) ) {

// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
// Note that this doesn't actually fix the selector due to potential false positives
migrateWarn( "Attribute selectors with '#' must be quoted: '" + selector + "'" );
// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
// Note that this doesn't actually fix the selector due to potential false positives
migrateWarn( "Attribute selectors with '#' must be quoted: '" + selector + "'" );
}
}

ret = oldInit.apply( this, arguments );
Expand Down
28 changes: 27 additions & 1 deletion test/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ test( "jQuery( '#' )", function() {
});

test( "attribute selectors with naked '#'", function() {
expect( 6 );
expect( 7 );

// These are wrapped in try/catch because they throw on jQuery 1.12.0+

Expand Down Expand Up @@ -102,8 +102,34 @@ test( "attribute selectors with naked '#'", function() {
jQuery( "a[href=\"#junk\"]" );
} catch( e ) {}
});

expectNoWarning( "function containing tempting string (#178)", function() {
try {
jQuery( function() {
if ( jQuery.thisIsNeverDefined ) {
jQuery( "a[href=#junk]" );
}
} );
} catch( e ) {}
});
});

QUnit.test( "document.context defined (#178)", function( assert ) {
assert.expect( 1 );

var span = jQuery( "<span>hi</span>" ).appendTo( "#qunit-fixture" );
try {
document.context = "!!hosed!!";
span.wrap( "<p></p>" );
assert.ok( true, "document.context did not kill jQuery" );
} catch ( err ) {
assert.ok( false, "died while wrapping" );
}

// Can't delete this property because of oldIE
document.context = null;
} );

test( "selector state", function() {
expect( 18 );

Expand Down

0 comments on commit c09b6a0

Please sign in to comment.