Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: Unhandled False in FileHandler
### PHP Version

8.3, 8.2

### CodeIgniter4 Version

4.6.0

### CodeIgniter4 Installation Method

Composer (using `codeigniter4/appstarter`)

### Which operating systems have you tested for this bug?

Linux

### Which server did you use?

fpm-fcgi

### Database

PostgreSQL 15

### What happened?

In system/Cache/Handlers/FileHandler.php, inside the getItem() method, the call to file_get_contents() can return false, which currently leads to a fatal error that crashes the application without any explanatory message. It would be preferable to:

Detect when file_get_contents() returns false.
In that case, ignore the cached file and regenerate the cache entry.
Emit a clear warning to the console indicating that reading the cache failed, so developers aren’t left with a silent crash.

### Steps to Reproduce

1. Make cache unreadable (for example, no permissions)
2. Try to get it

### Expected Output

Warning or error in console, no crash, recalculate of cache

### Anything else?

_No response_


Discussion:
> which currently leads to a fatal error that crashes the application without any explanatory message

That statement is incorrect - the code doesn't crash. It uses `@unserialize(...)` and returns `false` if the result isn't an array, so any issues (like unreadable files or invalid data) fail silently rather than causing a fatal error.

Also, in what scenario would the files lack proper permissions? They were created by the application in the first place.

In CLI

[TypeError]
unserialize(): Argument #1 ($data) must be of type string, bool given
at SYSTEMPATH/Cache/Handlers/FileHandler.php:228

Backtrace:
  1    SYSTEMPATH/Cache/Handlers/FileHandler.php:228
       unserialize(false)

  2    SYSTEMPATH/Cache/Handlers/FileHandler.php:81
       CodeIgniter\Cache\Handlers\FileHandler()->getItem('TESTCACHE')


![Image](https://github.com/user-attachments/assets/e8928cbc-20ca-4699-bf82-099219f0e755)

Just make unavailable to read

Ok, thank you for the follow-up. You're right, I forgot that suppressing errors like this no longer works in PHP 8+. I will send a fix later.



Patch:
diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php
index 4fd03e7921b0..c496143f62d9 100644
--- a/system/Cache/Handlers/FileHandler.php
+++ b/system/Cache/Handlers/FileHandler.php
@@ -217,7 +217,7 @@ public function isSupported(): bool
 
     /**
      * Does the heavy lifting of actually retrieving the file and
-     * verifying it's age.
+     * verifying its age.
      *
      * @return array{data: mixed, ttl: int, time: int}|false
      */
@@ -227,7 +227,17 @@ protected function getItem(string $filename)
             return false;
         }
 
-        $data = @unserialize(file_get_contents($this->path . $filename));
+        $content = @file_get_contents($this->path . $filename);
+
+        if ($content === false) {
+            return false;
+        }
+
+        try {
+            $data = unserialize($content);
+        } catch (Throwable) {
+            return false;
+        }
 
         if (! is_array($data)) {
             return false;
diff --git a/user_guide_src/source/changelogs/v4.6.2.rst b/user_guide_src/source/changelogs/v4.6.2.rst
index c55eda3e3787..936c0e709046 100644
--- a/user_guide_src/source/changelogs/v4.6.2.rst
+++ b/user_guide_src/source/changelogs/v4.6.2.rst
@@ -35,6 +35,7 @@ Deprecations
 Bugs Fixed
 **********
 
+- **Cache:** Fixed a bug where a corrupted or unreadable cache file could cause an unhandled exception in ``FileHandler::getItem()``.
 - **Database:** Fixed a bug where ``when()`` and ``whenNot()`` in ``ConditionalTrait`` incorrectly evaluated certain falsy values (such as ``[]``, ``0``, ``0.0``, and ``'0'``) as truthy, causing callbacks to be executed unexpectedly. These methods now cast the condition to a boolean using ``(bool)`` to ensure consistent behavior with PHP's native truthiness.
 - **Security:** Fixed a bug where the ``sanitize_filename()`` function from the Security helper would throw an error when used in CLI requests.
 - **Session:** Fixed a bug where using the ``DatabaseHandler`` with an unsupported database driver (such as ``SQLSRV``, ``OCI8``, or ``SQLite3``) did not throw an appropriate error.


Test patch:
diff --git a/tests/system/Cache/Handlers/FileHandlerTest.php b/tests/system/Cache/Handlers/FileHandlerTest.php
index 4c45a0712f64..ed163071aede 100644
--- a/tests/system/Cache/Handlers/FileHandlerTest.php
+++ b/tests/system/Cache/Handlers/FileHandlerTest.php
@@ -363,6 +363,30 @@ public function testGetMetaDataMiss(): void
     {
         $this->assertFalse($this->handler->getMetaData(self::$dummy));
     }
+
+    #[RequiresOperatingSystem('Linux|Darwin')]
+    public function testGetUnreadableFile(): void
+    {
+        $this->handler->save(self::$key1, 'value');
+
+        $filePath = $this->config->file['storePath'] . DIRECTORY_SEPARATOR . $this->config->prefix . self::$key1;
+
+        // Make the file unreadable
+        chmod($filePath, 0000);
+
+        $this->assertNull($this->handler->get(self::$key1));
+    }
+
+    public function testGetItemWithCorruptedData(): void
+    {
+        $filePath = $this->config->file['storePath'] . DIRECTORY_SEPARATOR . $this->config->prefix . self::$key1;
+
+        file_put_contents($filePath, 'corrupted_serialized_data_that_cannot_be_unserialized');
+
+        $this->assertFileExists($filePath);
+
+        $this->assertNull($this->handler->get(self::$key1));
+    }
 }
 
 final class BaseTestFileHandler extends FileHandler