Index: src/wp-admin/includes/post.php
===================================================================
--- src/wp-admin/includes/post.php	(revision 26622)
+++ src/wp-admin/includes/post.php	(working copy)
@@ -346,11 +346,14 @@
 			unset($post_data[$field]);
 	}
 
-	if ( isset($post_data['post_category']) ) {
-		if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
+	$taxonomy_obj = get_taxonomy( 'category' );
+	if ( $taxonomy_obj && isset( $post_data['post_category'] ) ) {
+		if ( is_array( $post_data['post_category'] ) && ! empty( $post_data['post_category'] ) ) {
 			$new_cats = array_map( 'absint', $post_data['post_category'] );
-		else
-			unset($post_data['post_category']);
+		}
+		else {
+			unset( $post_data['post_category'] );
+		}
 	}
 
 	$tax_input = array();
@@ -403,10 +406,15 @@
 		$tax_names = get_object_taxonomies( $post );
 		foreach ( $tax_names as $tax_name ) {
 			$taxonomy_obj = get_taxonomy($tax_name);
-			if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) )
+			if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
 				$new_terms = $tax_input[$tax_name];
-			else
+				if ( ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
+					$new_terms = wp_strip_new_terms( $new_terms, $tax_name );
+				}
+			}
+			else {
 				$new_terms = array();
+			}
 
 			if ( $taxonomy_obj->hierarchical )
 				$current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') );
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 26622)
+++ src/wp-includes/post.php	(working copy)
@@ -2906,20 +2906,35 @@
 		$wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
 	}
 
-	if ( is_object_in_taxonomy($post_type, 'category') )
+	$taxonomy_obj = get_taxonomy( 'category' );
+	if ( $taxonomy_obj && is_object_in_taxonomy( $post_type, $taxonomy_obj->name ) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
+		if ( ! is_taxonomy_hierarchical( $taxonomy_obj->name ) && ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
+			$post_category = wp_strip_new_terms( $post_category, $taxonomy_obj->name );
+		}
 		wp_set_post_categories( $post_ID, $post_category );
+	}
 
-	if ( isset( $tags_input ) && is_object_in_taxonomy($post_type, 'post_tag') )
+	$taxonomy_obj = get_taxonomy( 'post_tag' );
+	if ( $taxonomy_obj && isset( $tags_input ) && is_object_in_taxonomy( $post_type, $taxonomy_obj->name ) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
+		if ( ! is_taxonomy_hierarchical( $taxonomy_obj->name ) && ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
+			$tags_input = wp_strip_new_terms( $tags_input, $taxonomy_obj->name );
+		}
 		wp_set_post_tags( $post_ID, $tags_input );
+	}
 
 	// new-style support for all custom taxonomies
-	if ( !empty($tax_input) ) {
-		foreach ( $tax_input as $taxonomy => $tags ) {
-			$taxonomy_obj = get_taxonomy($taxonomy);
-			if ( is_array($tags) ) // array = hierarchical, string = non-hierarchical.
-				$tags = array_filter($tags);
-			if ( current_user_can($taxonomy_obj->cap->assign_terms) )
-				wp_set_post_terms( $post_ID, $tags, $taxonomy );
+	if ( ! empty( $tax_input ) ) {
+		foreach ( $tax_input as $taxonomy => $terms ) {
+			$taxonomy_obj = get_taxonomy( $taxonomy );
+			if ( $taxonomy_obj && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
+				if ( is_array( $terms ) ) { // array = hierarchical, string = non-hierarchical.
+					$terms = array_filter( $terms );
+				}
+				if ( ! is_taxonomy_hierarchical( $taxonomy_obj->name ) && ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
+					$terms = wp_strip_new_terms( $terms, $taxonomy_obj->name );
+				}
+				wp_set_post_terms( $post_ID, $terms, $taxonomy );
+			}
 		}
 	}
 
@@ -3286,6 +3301,42 @@
 }
 
 /**
+ * Filter out any terms that don't already exist. Not applicable to
+ * hierarchical taxonomies.
+ *
+ * @param array $terms
+ * @param string $taxonomy
+ *
+ * @return array
+ */
+function wp_strip_new_terms( $terms, $taxonomy ) {
+
+	if ( ! taxonomy_exists( $taxonomy ) || is_taxonomy_hierarchical( $taxonomy ) ) {
+		return $terms;
+	}
+
+	if ( empty( $terms ) ) {
+		$terms = array();
+	}
+	if ( ! is_array( $terms ) ) {
+		$comma = _x( ',', 'tag delimiter' );
+		if ( ',' !== $comma ) {
+			$terms = str_replace( $comma, ',', $terms );
+		}
+		$terms = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) );
+	}
+
+	$new_terms = array();
+	foreach( $terms as $term ) {
+		if ( ! term_exists( $term, $taxonomy ) ) {
+			$new_terms[] = $term;
+		}
+	}
+	$terms = array_diff( $terms, $new_terms );
+	return $terms;
+}
+
+/**
  * Transition the post status of a post.
  *
  * Calls hooks to transition post status.
