Index: src/wp-includes/theme.php
===================================================================
--- src/wp-includes/theme.php	(revision 26164)
+++ src/wp-includes/theme.php	(working copy)
@@ -1261,6 +1261,7 @@
  */
 function add_theme_support( $feature ) {
 	global $_wp_theme_features;
+	static $_back_compat = array();
 
 	if ( func_num_args() == 1 )
 		$args = true;
@@ -1323,36 +1324,42 @@
 			if ( $jit )
 				$args[0] = wp_parse_args( $args[0], $defaults );
 
-			// If a constant was defined, use that value. Otherwise, define the constant to ensure
-			// the constant is always accurate (and is not defined later,  overriding our value).
+			// Make sure the code below runs only once, otherwise the defined constants will keep
+			// overriding the $args, regardless of whether they've been removed with remove_theme_support().
+
+			if ( ! isset( $_back_compat[ $feature ] ) ) {
+				$_back_compat[ $feature ] = array();
+			}
+
+			$_back_compat[ $feature ] = array_merge( $_back_compat[ $feature ], array_map( '__return_true', $args[0] ) );
+
+			// If a constant was defined, use that value, but only use it once.
 			// As stated above, the first value wins.
-			// Once we get to wp_loaded (just-in-time), define any constants we haven't already.
-			// Constants are lame. Don't reference them. This is just for backwards compatibility.
 
-			if ( defined( 'NO_HEADER_TEXT' ) )
+			if ( defined( 'NO_HEADER_TEXT' ) && ! isset( $_back_compat[ $feature ]['header-text'] ) ) {
 				$args[0]['header-text'] = ! NO_HEADER_TEXT;
-			elseif ( isset( $args[0]['header-text'] ) )
-				define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
+				$_back_compat[ $feature ]['header-text'] = true;
+			}
 
-			if ( defined( 'HEADER_IMAGE_WIDTH' ) )
+			if ( defined( 'HEADER_IMAGE_WIDTH' ) && ! isset( $_back_compat[ $feature ]['width'] ) ) {
 				$args[0]['width'] = (int) HEADER_IMAGE_WIDTH;
-			elseif ( isset( $args[0]['width'] ) )
-				define( 'HEADER_IMAGE_WIDTH', (int) $args[0]['width'] );
+				$_back_compat[ $feature ]['width'] = true;
+			}
 
-			if ( defined( 'HEADER_IMAGE_HEIGHT' ) )
+			if ( defined( 'HEADER_IMAGE_HEIGHT' ) && ! isset( $_back_compat[ $feature ]['height'] ) ) {
 				$args[0]['height'] = (int) HEADER_IMAGE_HEIGHT;
-			elseif ( isset( $args[0]['height'] ) )
-				define( 'HEADER_IMAGE_HEIGHT', (int) $args[0]['height'] );
+				$_back_compat[ $feature ]['height'] = true;
+			}
 
-			if ( defined( 'HEADER_TEXTCOLOR' ) )
+			if ( defined( 'HEADER_TEXTCOLOR' ) && ! isset( $_back_compat[ $feature ]['default-text-color'] ) ) {
 				$args[0]['default-text-color'] = HEADER_TEXTCOLOR;
-			elseif ( isset( $args[0]['default-text-color'] ) )
-				define( 'HEADER_TEXTCOLOR', $args[0]['default-text-color'] );
+				$_back_compat[ $feature ]['default-text-color'] = true;
+			}
 
-			if ( defined( 'HEADER_IMAGE' ) )
+			if ( defined( 'HEADER_IMAGE' ) && ! isset( $_back_compat[ $feature ]['default-image'] )  ) {
 				$args[0]['default-image'] = HEADER_IMAGE;
-			elseif ( isset( $args[0]['default-image'] ) )
-				define( 'HEADER_IMAGE', $args[0]['default-image'] );
+				$_back_compat[ $feature ]['default-image'] = true;
+			}
 
 			if ( $jit && ! empty( $args[0]['default-image'] ) )
 				$args[0]['random-default'] = false;
@@ -1366,6 +1373,30 @@
 					$args[0]['flex-height'] = true;
 			}
 
+			// Once we get to wp_loaded (just-in-time), define any constants we haven't already.
+			// Constants are lame. Don't reference them. This is just for backwards compatibility.
+			if ( $jit ) {
+				if ( ! defined( 'NO_HEADER_TEXT' ) ) {
+					define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
+				}
+
+				if ( ! defined( 'HEADER_IMAGE_WIDTH' ) ) {
+					define( 'HEADER_IMAGE_WIDTH', (int) $args[0]['width'] );
+				}
+
+				if ( ! defined( 'HEADER_IMAGE_HEIGHT' ) ) {
+					define( 'HEADER_IMAGE_HEIGHT', (int) $args[0]['height'] );
+				}
+
+				if ( ! defined( 'HEADER_TEXTCOLOR' ) ) {
+					define( 'HEADER_TEXTCOLOR', $args[0]['default-text-color'] );
+				}
+
+				if ( ! defined( 'HEADER_IMAGE' ) ) {
+					define( 'HEADER_IMAGE', $args[0]['default-image'] );
+				}
+			}
+
 			break;
 
 		case 'custom-background' :
Index: tests/phpunit/tests/theme/support.php
===================================================================
--- tests/phpunit/tests/theme/support.php	(revision 26164)
+++ tests/phpunit/tests/theme/support.php	(working copy)
@@ -156,4 +156,49 @@
 		remove_theme_support( 'foobar' );
 		$this->assertFalse( current_theme_supports( 'foobar', 'bar' ) );
 	}
+
+	/**
+	 * @ticket 25333
+	 */
+	function test_remove_theme_support() {
+
+		// At this point, the default theme has (probably) already registered custom header support.
+		$original_width = get_theme_support( 'custom-header', 'width' );
+		$original_image = get_theme_support( 'custom-header', 'default-image' );
+
+		$this->assertTrue( defined( 'HEADER_IMAGE_WIDTH' ) );
+		$this->assertTrue( defined( 'HEADER_IMAGE' ) );
+		$this->assertEquals( HEADER_IMAGE_WIDTH, $original_width );
+		$this->assertEquals( HEADER_IMAGE, $original_image );
+
+		remove_theme_support( 'custom-header' );
+		$this->assertFalse( current_theme_supports( 'custom-header' ) );
+
+		// First registered value wins, because child themes are loaded earlier.
+		add_theme_support( 'custom-header', array( 'default-image' => 'foo' ) );
+		$this->assertEquals( 'foo', get_theme_support( 'custom-header', 'default-image' ) );
+
+		// This should not override the above.
+		add_theme_support( 'custom-header', array( 'default-image' => 'bar' ) );
+		$this->assertEquals( 'foo', get_theme_support( 'custom-header', 'default-image' ) );
+
+		// This, however, should override whatever has been set.
+		remove_theme_support( 'custom-header' );
+		add_theme_support( 'custom-header', array( 'default-image' => 'baz' ) );
+		$this->assertEquals( 'baz', get_theme_support( 'custom-header', 'default-image' ) );
+
+		// Second call to add_theme_support should merge the arguments with the first.
+		remove_theme_support( 'custom-header' );
+		add_theme_support( 'custom-header', array( 'width' => 123 ) );
+		add_theme_support( 'custom-header', array( 'height' => 456 ) );
+		$this->assertEquals( 123, get_theme_support( 'custom-header', 'width' ) );
+		$this->assertEquals( 456, get_theme_support( 'custom-header', 'height' ) );
+
+		// Second call to add_theme_support should not override arguments set in the first.
+		remove_theme_support( 'custom-header' );
+		add_theme_support( 'custom-header', array( 'width' => 123 ) );
+		add_theme_support( 'custom-header', array( 'width' => 789, 'height' => 456 ) );
+		$this->assertEquals( 123, get_theme_support( 'custom-header', 'width' ) );
+		$this->assertEquals( 456, get_theme_support( 'custom-header', 'height' ) );
+	}
 }
