codeigniter4 / codeigniter4/CodeIgniter4
Bug: FileVarExportHandler silently drops the TTL passed by FileLocatorCached, so the locator cache never expires
- Ngôn ngữ chính
- PHP
- Star
- 6k
- Fork
- 2k
- Merge trung bình
- 1 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 73
Mô tả
### PHP Version
8.5
### CodeIgniter4 Version
4.7.4
### CodeIgniter4 Installation Method
Manual (zip or tar.gz)
### Which operating systems have you tested for this bug?
macOS, Linux
### Which server did you use?
cli
### Environment
production
### Database
Not relevant to this bug.
### What happened?
`FileLocatorCached::saveCache()` passes a 24-hour TTL to the cache handler:
```php
// system/Autoloader/FileLocatorCached.php:75-80 (v4.7.4)
private function saveCache(): void
{
if ($this->cacheUpdated) {
$this->cacheHandler->save($this->cacheKey, $this->cache, 3600 * 24);
}
}
```
But `FileVarExportHandler::save()` declares only two parameters:
```php
// system/Cache/FactoriesCache/FileVarExportHandler.php:20 (v4.7.4)
public function save(string $key, mixed $val): void
```
PHP silently discards an extra argument passed to a non-variadic userland function, so the
TTL never reaches the handler — no error, no warning, no log entry. Nothing about expiry is
written to the cache file, and `get()` is a bare include with no expiry check at all:
```php
// system/Cache/FactoriesCache/FileVarExportHandler.php:53-56 (v4.7.4)
public function get(string $key): mixed
{
return @include $this->path . "/{$key}";
}
```
The result is that the locator cache **never expires**, while the calling code states that it
should expire after 24 hours. A file discovered by the locator — for instance a
`Config/Registrar.php` shipped by a package or added by the application — stays invisible for
as long as the cache file exists on disk, not for the 24 hours the call site intends.
Both files are identical in v4.7.3, v4.7.4 and on the default branch at the time of writing.
### Steps to Reproduce
1. Enable the locator cache: `php spark optimize`, which sets `$locatorCacheEnabled = true`
in `app/Config/Optimize.php`.
2. Run any command or request, so that the cache file is written to
`writable/cache/FactoriesCache_FileLocatorCache`.
3. Open that file. It contains `cacheUpdated = false`, but any locator lookup afterwards in the same process sets
`$this->cacheUpdated = true` again, and `__destruct()` (`:70-73`) then writes the old
in-memory state back to disk. So a "clear the cache, then continue working" sequence inside
one process can end with the stale file restored.
We hit the original bug in a deployment: a `Config/Registrar.php` added to the disk after the
cache had been warmed stayed invisible, and every route protected by the filter aliases it
declares answered HTTP 500. Our workaround is to delete the cache file from a separate
process (a plain `rm -f` in the deploy script) rather than from PHP, which is a workaround
for the second detail above rather than for the missing TTL.
This replaces #10537, opened by the same account and closed automatically by
`mergeable[bot]` because it did not follow this template. It is the same defect, refiled in
the required form: the account cannot reopen the original issue, so this is a new one rather
than a duplicate report.
Hướng dẫn đóng góp
Hướng nghiên cứu
Đọc system/Autoloader/FileLocatorCached.php và system/Cache/FactoriesCache/FileVarExportHandler.php, tập trung vào saveCache(), save(), get(), deleteCache() và __destruct(). Chạy php spark optimize và kiểm tra writable/cache/FactoriesCache_FileLocatorCache để xác minh hành vi hiện tại. Hoàn tất khi caller và handler thống nhất về thời hạn hết hạn của cache, đồng thời hành vi 24 giờ được ghi lại trong tài liệu hoặc một contract không hết hạn được chỉ rõ được thực thi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- php
- Lĩnh vực
- backend
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 68/100