Index: wp-includes/default-filters.php
===================================================================
--- wp-includes/default-filters.php	(revision 21626)
+++ wp-includes/default-filters.php	(working copy)
@@ -192,6 +192,7 @@
 add_filter( 'editable_slug',            'urldecode'                           );
 add_filter( 'editable_slug',            'esc_textarea'                        );
 add_filter( 'nav_menu_meta_box_object', '_wp_nav_menu_meta_box_object'        );
+add_filter( 'wp_search_stopwords',      'wp_search_stopwords'                 );
 
 // Actions
 add_action( 'wp_head',             'wp_enqueue_scripts',              1     );
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 21626)
+++ wp-includes/functions.php	(working copy)
@@ -3637,3 +3637,26 @@
 	return true;
 }
 
+/**
+ * Common stopwords (terms) that are excluded from the separate term matching when searching for posts.
+ * The list of English stopwords is the approximate search engines list. MySQL has a much longer default list of full-text stopwords.
+ *
+ * @since 3.5.0
+ * @param array optional Terms to exclude when searching
+ *
+ * @return array
+ */
+function wp_search_stopwords( $in = array() ) {
+	$_words = explode( ',', _x('about,are,com,for,from,how,that,the,this,was,what,when,where,who,will,with,www', 'Comma separated list of common words to exclude when searching.') );
+	$words = array();
+
+	foreach( $_words as $word ) {
+		$word = trim($word, "\r\n\t ");
+		if ( !$word )
+			continue;
+		$words[] = $word;
+	}
+
+	return array_merge( $in, $words );
+}
+
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 21626)
+++ wp-includes/query.php	(working copy)
@@ -2173,8 +2173,10 @@
 			}
 		}
 
-		// If a search pattern is specified, load the posts that match
-		if ( !empty($q['s']) ) {
+		// If a search pattern is specified, load the posts that match.
+		// Sanity check: search string shouldn't be more than 1600 characters.
+		// See ticket #21688 for more info.
+		if ( !empty($q['s']) && strlen($q['s']) < 1600 ) {
 			// added slashes screw with quote grouping when done early, so done later
 			$q['s'] = stripslashes($q['s']);
 			if ( empty( $_GET['s'] ) && $this->is_main_query() )
@@ -2183,11 +2185,26 @@
 				$q['search_terms'] = array($q['s']);
 			} else {
 				preg_match_all('/".*?("|$)|((?<=[\r\n\t ",+])|^)[^\r\n\t ",+]+/', $q['s'], $matches);
-				$q['search_terms'] = array_map('_search_terms_tidy', $matches[0]);
+				$_search_terms = array_map('_search_terms_tidy', $matches[0]);
+				$q['search_terms'] = array();
+				$stopwords = apply_filters_ref_array( 'wp_search_stopwords', array( array(), &$this ) );
+				$strtolower_func = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
+
+				foreach ( (array) $_search_terms as $term ) {
+					if ( empty( $term{2} ) || in_array( $strtolower_func($term), $stopwords, true ) )
+						continue;
+					$q['search_terms'][] = $term;
+				}
+
+				unset($_search_terms);
+				// if the search string has only short terms or stopwords, or is more than 10 terms long, match it as sentence
+				if ( empty($q['search_terms']) || count($q['search_terms']) > 10 )
+					$q['search_terms'] = array($q['s']);
 			}
+
 			$n = !empty($q['exact']) ? '' : '%';
 			$searchand = '';
-			foreach( (array) $q['search_terms'] as $term ) {
+			foreach( $q['search_terms'] as $term ) {
 				$term = esc_sql( like_escape( $term ) );
 				$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
 				$searchand = ' AND ';
