diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 8bd6a1821162e..a2779651d2e6f 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -1464,7 +1464,9 @@ function get_transient( $transient ) { $transient_timeout = '_transient_timeout_' . $transient; wp_prime_option_caches( array( $transient_option, $transient_timeout ) ); $timeout = get_option( $transient_timeout ); - if ( false !== $timeout && $timeout < time() ) { + if ( false === $timeout ) { + $value = false; + } elseif ( $timeout < time() ) { delete_option( $transient_option ); delete_option( $transient_timeout ); $value = false; diff --git a/tests/phpunit/tests/option/transient.php b/tests/phpunit/tests/option/transient.php index d4f6c6ce43ae9..034973d9bc6ae 100644 --- a/tests/phpunit/tests/option/transient.php +++ b/tests/phpunit/tests/option/transient.php @@ -265,4 +265,23 @@ public function test_nonexistent_key_old_timeout() { ); $this->assertSame( $expected, $a->get_events() ); } + + /** + * Ensure get_transient() returns false when the transient timeout option is missing (broken transient). + * + * @ticket 33561 + * + * @covers ::get_transient + */ + public function test_get_transient_returns_false_when_timeout_is_missing() { + $key = 'test_transient_broken'; + $value = 'test_value'; + + set_transient( $key, $value, 60 * 10 ); + $this->assertSame( $value, get_transient( $key ) ); + + delete_option( '_transient_timeout_' . $key ); + + $this->assertFalse( get_transient( $key ) ); + } }