diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php
index bc25dd0045a87..a1f4a5ea7eea8 100644
--- a/src/wp-admin/includes/class-wp-posts-list-table.php
+++ b/src/wp-admin/includes/class-wp-posts-list-table.php
@@ -1781,7 +1781,7 @@ public function inline_edit() {
diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php
index ebdd61df345dc..ca88e537bd2a1 100644
--- a/src/wp-admin/includes/post.php
+++ b/src/wp-admin/includes/post.php
@@ -156,6 +156,10 @@ function _wp_translate_postdata( $update = false, $post_data = null ) {
unset( $post_data['post_password'] );
}
+ if ( isset( $post_data['post_password'] ) && strlen( $post_data['post_password'] ) > 255 ) {
+ return new WP_Error( 'invalid_post_password_length', __( 'Post passwords cannot be longer than 255 characters.' ) );
+ }
+
if ( ! isset( $post_data['comment_status'] ) ) {
$post_data['comment_status'] = 'closed';
}
diff --git a/tests/phpunit/tests/admin/includesPost.php b/tests/phpunit/tests/admin/includesPost.php
index de7b42f5eb15a..0cde7b8745104 100644
--- a/tests/phpunit/tests/admin/includesPost.php
+++ b/tests/phpunit/tests/admin/includesPost.php
@@ -26,6 +26,9 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
self::$post_id = $factory->post->create();
}
+ /**
+ * @covers ::_wp_translate_postdata
+ */
public function test__wp_translate_postdata_cap_checks_contributor() {
wp_set_current_user( self::$contributor_id );
@@ -1325,4 +1328,55 @@ public function test_user_get_refreshed_metabox_nonce() {
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['_wpnonce'] );
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['metabox_loader_nonce'] );
}
+
+ /**
+ * Test that _wp_translate_postdata() validates post password length.
+ *
+ * @ticket 63943
+ * @covers ::_wp_translate_postdata
+ */
+ public function test_validity_post_password_length() {
+ wp_set_current_user( self::$editor_id );
+
+ // Test valid password within 255 character limit.
+ $valid_password = str_repeat( 'a', 255 );
+ $post_data = array(
+ 'post_type' => 'post',
+ 'post_password' => $valid_password,
+ );
+
+ $result = _wp_translate_postdata( false, $post_data );
+ $this->assertNotWPError( $result );
+ $this->assertSame( $valid_password, $result['post_password'] );
+
+ // Test password over 255 characters should fail.
+ $invalid_password = str_repeat( 'a', 256 );
+ $post_data = array(
+ 'post_type' => 'post',
+ 'post_password' => $invalid_password,
+ );
+
+ $result = _wp_translate_postdata( false, $post_data );
+ $this->assertWPError( $result );
+ $this->assertSame( 'invalid_post_password_length', $result->get_error_code() );
+ }
+
+ /**
+ * Test that _wp_translate_postdata() removes post password for users without publish_posts capability.
+ *
+ * @covers ::_wp_translate_postdata
+ */
+ public function test_post_password_removed_for_users_without_publish_posts_cap() {
+ wp_set_current_user( self::$contributor_id );
+
+ // Contributors cannot publish posts, so password should be removed.
+ $post_data = array(
+ 'post_type' => 'post',
+ 'post_password' => 'test_password',
+ 'post_status' => 'draft',
+ );
+
+ $result = _wp_translate_postdata( false, $post_data );
+ $this->assertArrayNotHasKey( 'post_password', $result );
+ }
}