From 442484ba50c6b2ee07f8b43bc8001bff0163476a Mon Sep 17 00:00:00 2001 From: chriszarate Date: Mon, 2 Mar 2026 16:10:53 -0700 Subject: [PATCH] Prevent fallthrough in sync polling server --- .../class-wp-http-polling-sync-server.php | 5 ++- .../tests/rest-api/rest-sync-server.php | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/collaboration/class-wp-http-polling-sync-server.php b/src/wp-includes/collaboration/class-wp-http-polling-sync-server.php index bc9d208f096be..54fc9d19634f1 100644 --- a/src/wp-includes/collaboration/class-wp-http-polling-sync-server.php +++ b/src/wp-includes/collaboration/class-wp-http-polling-sync-server.php @@ -402,7 +402,10 @@ private function process_sync_update( string $room, int $client_id, int $cursor, return $this->add_update( $room, $client_id, $type, $data ); } - break; + + // Reaching this point means there's a newer compaction, so we can + // silently ignore this one. + return true; case self::UPDATE_TYPE_SYNC_STEP1: case self::UPDATE_TYPE_SYNC_STEP2: diff --git a/tests/phpunit/tests/rest-api/rest-sync-server.php b/tests/phpunit/tests/rest-api/rest-sync-server.php index 0180f02ca3b45..e35286b07d6e5 100644 --- a/tests/phpunit/tests/rest-api/rest-sync-server.php +++ b/tests/phpunit/tests/rest-api/rest-sync-server.php @@ -623,6 +623,48 @@ public function test_sync_should_compact_is_false_for_non_compactor() { $this->assertFalse( $data['rooms'][0]['should_compact'] ); } + public function test_sync_stale_compaction_succeeds_when_newer_compaction_exists() { + wp_set_current_user( self::$editor_id ); + + $room = $this->get_post_room(); + $update = array( + 'type' => 'update', + 'data' => 'dGVzdA==', + ); + + // Client 1 sends an update to seed the room. + $response = $this->dispatch_sync( + array( + $this->build_room( $room, 1, 0, array( 'user' => 'c1' ), array( $update ) ), + ) + ); + + $end_cursor = $response->get_data()['rooms'][0]['end_cursor']; + + // Client 2 sends a compaction at the current cursor. + $compaction = array( + 'type' => 'compaction', + 'data' => 'Y29tcGFjdGVk', + ); + + $this->dispatch_sync( + array( + $this->build_room( $room, 2, $end_cursor, array( 'user' => 'c2' ), array( $compaction ) ), + ) + ); + + // Client 3 sends a stale compaction at cursor 0. The server should find + // client 2's compaction in the updates after cursor 0 and silently discard + // this one. + $response = $this->dispatch_sync( + array( + $this->build_room( $room, 3, 0, array( 'user' => 'c3' ), array( $compaction ) ), + ) + ); + + $this->assertSame( 200, $response->get_status() ); + } + /* * Awareness tests. */