Index: wp-includes/shortcodes.php
===================================================================
--- wp-includes/shortcodes.php	(revision 17831)
+++ wp-includes/shortcodes.php	(working copy)
@@ -148,7 +148,7 @@
 		return $content;
 
 	$pattern = get_shortcode_regex();
-	return preg_replace_callback('/'.$pattern.'/s', 'do_shortcode_tag', $content);
+	return preg_replace_callback( "/$pattern/sx", 'do_shortcode_tag', $content );
 }
 
 /**
@@ -175,8 +175,42 @@
 	$tagnames = array_keys($shortcode_tags);
 	$tagregexp = join( '|', array_map('preg_quote', $tagnames) );
 
-	// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcodes()
-	return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)';
+	// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
+	return "
+		\\[                              # Opening bracket
+		(\\[?)                           # 1: Optional second opening bracket for escaping shortcodes: [[tag]]
+		( $tagregexp )                   # 2: Shortcode name
+		\\b                              # Word boundary
+		(                                # 3: Unroll the loop: Inside the opening shortcode tag
+		    [^\\]'\"\\/]*                # Not a closing bracket, single or double quote, or forward slash
+		    (?:
+		        (?:
+		            '[^']*+'             # Anything in single quotes
+		        |
+		            \"[^\"]*+\"          # Anything in double quotes
+		        |
+		            \\/(?!\\])           # A forward slash not followed by a closing bracket
+		        )
+		        [^\\]'\"\\/]*            # Not a closing bracket, single or double quote, or forward slash
+		    )*?
+		)
+		(?:
+		    \\/\\]                       # Self closing tag and closing bracket
+		|
+		    \\]                          # Closing bracket
+		    (?:
+		        (                        # 4: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
+		            [^\\[]*+             # Not an opening bracket
+		            (?:
+		                \\[(?!\\/\\2\\]) # An opening bracket not followed by the closing shortcode tag
+		                [^\\[]*+         # Not an opening bracket
+		            )*+
+		        )
+		        \\[\\/\\2\\]             # Closing shortcode tag
+		    )?
+		)
+		(\\]?)                           # 5: Optional second closing brocket for escaping shortcodes: [[tag]]
+	";
 }
 
 /**
@@ -194,19 +228,19 @@
 	global $shortcode_tags;
 
 	// allow [[foo]] syntax for escaping a tag
-	if ( $m[1] == '[' && $m[6] == ']' ) {
+	if ( $m[1] == '[' && $m[5] == ']' ) {
 		return substr($m[0], 1, -1);
 	}
 
 	$tag = $m[2];
 	$attr = shortcode_parse_atts( $m[3] );
 
-	if ( isset( $m[5] ) ) {
+	if ( isset( $m[4] ) ) {
 		// enclosing tag - extra parameter
-		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[5], $tag ) . $m[6];
+		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[4], $tag ) . $m[5];
 	} else {
 		// self-closing tag
-		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, NULL,  $tag ) . $m[6];
+		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, NULL,  $tag ) . $m[5];
 	}
 }
 
@@ -290,9 +324,18 @@
 
 	$pattern = get_shortcode_regex();
 
-	return preg_replace('/'.$pattern.'/s', '$1$6', $content);
+	return preg_replace_callback( "/$pattern/sx", 'strip_shortcode_tag', $content );
 }
 
+function strip_shortcode_tag( $m ) {
+	// allow [[foo]] syntax for escaping a tag
+	if ( $m[1] == '[' && $m[5] == ']' ) {
+		return substr($m[0], 1, -1);
+	}
+
+	return $m[1] . $m[5];
+} 
+
 add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop()
 
-?>
\ No newline at end of file
+?>
Index: wp-includes/formatting.php
===================================================================
--- wp-includes/formatting.php	(revision 17831)
+++ wp-includes/formatting.php	(working copy)
@@ -232,16 +232,53 @@
  * @param string $pee The content.
  * @return string The filtered content.
  */
-function shortcode_unautop($pee) {
+function shortcode_unautop( $pee ) {
 	global $shortcode_tags;
 
-	if ( !empty($shortcode_tags) && is_array($shortcode_tags) ) {
-		$tagnames = array_keys($shortcode_tags);
-		$tagregexp = join( '|', array_map('preg_quote', $tagnames) );
-		$pee = preg_replace('/<p>\\s*?(\\[(' . $tagregexp . ')\\b.*?\\/?\\](?:.+?\\[\\/\\2\\])?)\\s*<\\/p>/s', '$1', $pee);
+	if ( empty( $shortcode_tags ) || !is_array( $shortcode_tags ) ) {
+		return $pee;
 	}
 
-	return $pee;
+	$tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) );
+
+	$pattern = "/
+		<p>                              # Opening paragraph
+		\\s*+                            # Optional leading whitespace
+		(                                # 1: The shortcode
+		    \\[                          # Opening bracket
+		    ( $tagregexp )               # 2: Shortcode name
+		    \\b                          # Word boundary
+		                                 # Unroll the loop: Inside the opening shortcode tag
+		    [^\\]'\"\\/]*                # Not a closing bracket, single or double quote, or forward slash
+		    (?:
+		        (?:
+		            '[^']*+'             # Anything in single quotes
+		        |
+		            \"[^\"]*+\"          # Anything in double quotes
+		        |
+		            \\/(?!\\])           # A forward slash not followed by a closing bracket
+		        )
+		        [^\\]'\"\\/]*            # Not a closing bracket, single or double quote, or forward slash
+		    )*?
+		    (?:
+		        \\/\\]                   # Self closing tag and closing bracket
+		    |
+		        \\]                      # Closing bracket
+		        (?:                      # Unroll the loop: Optionally, anything between the opening and closing shortcode tags
+		            [^\\[]*+             # Not an opening bracket
+		            (?:
+		                \\[(?!\\/\\2\\]) # An opening bracket not followed by the closing shortcode tag
+		                [^\\[]*+         # Not an opening bracket
+		            )*+
+		            \\[\\/\\2\\]         # Closing shortcode tag
+		        )?
+		    )
+		)
+		\\s*+                            # optional trailing whitespace
+		<\\/p>                           # closing paragraph
+	/sx";
+
+	return preg_replace( $pattern, '$1', $pee );
 }
 
 /**
