From 8202da512f7884cbf0d5d61d83fb780554dbb44a Mon Sep 17 00:00:00 2001 From: jwj <86849180@qq.com> Date: Sat, 14 Sep 2024 17:30:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BF=BD=E7=95=A5=E5=8F=8D?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=E6=95=B0=E6=8D=AE=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/think/cache/Driver.php | 31 +++++++++++++++++++++++----- src/think/cache/driver/File.php | 7 ++++--- src/think/cache/driver/Memcache.php | 7 ++++--- src/think/cache/driver/Memcached.php | 7 ++++--- src/think/cache/driver/Redis.php | 9 ++++---- src/think/cache/driver/Wincache.php | 5 +++-- tests/CacheTest.php | 23 ++++++++++++++++++++- 7 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/think/cache/Driver.php b/src/think/cache/Driver.php index 2929e5ac83..63cc2926f2 100644 --- a/src/think/cache/Driver.php +++ b/src/think/cache/Driver.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache; @@ -247,18 +248,38 @@ protected function serialize($data): string /** * 反序列化数据 * @access protected - * @param string $data 缓存数据 + * @param string $data 缓存数据 + * @param string $name 缓存名 + * @param mixed $default 默认值 * @return mixed */ - protected function unserialize(string $data) + protected function unserialize(string $data, string $name = '', mixed $default = null) { if (is_numeric($data)) { return $data; } - $unserialize = $this->options['serialize'][1] ?? "unserialize"; + set_error_handler(function ($code, $message, $filename, $line) { + throw new \ErrorException($message, $code, 0, $filename, $line); + }); + + try { + $unserialize = $this->options['serialize'][1] ?? 'unserialize'; + $content = $unserialize($data); + + restore_error_handler(); + } catch (Throwable $e) { + restore_error_handler(); + + if (empty($this->options['serialize'][2])) { + throw $e; + } else { + $content = $default; + $this->delete($name); + } + } - return $unserialize($data); + return $content; } /** diff --git a/src/think/cache/driver/File.php b/src/think/cache/driver/File.php index ecd960ad78..36ceb5e9af 100644 --- a/src/think/cache/driver/File.php +++ b/src/think/cache/driver/File.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache\driver; @@ -135,7 +136,7 @@ public function get($name, $default = null): mixed { $raw = $this->getRaw($name); - return is_null($raw) ? $default : $this->unserialize($raw['content']); + return is_null($raw) ? $default : $this->unserialize($raw['content'], $name, $default); } /** @@ -199,7 +200,7 @@ public function set($name, $value, $expire = null): bool public function inc($name, $step = 1) { if ($raw = $this->getRaw($name)) { - $value = $this->unserialize($raw['content']) + $step; + $value = $this->unserialize($raw['content'], $name, 0) + $step; $expire = $raw['expire']; } else { $value = $step; diff --git a/src/think/cache/driver/Memcache.php b/src/think/cache/driver/Memcache.php index f8f4fbfd5c..348ce964d3 100644 --- a/src/think/cache/driver/Memcache.php +++ b/src/think/cache/driver/Memcache.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache\driver; @@ -52,7 +53,7 @@ public function __construct(array $options = []) $this->options = array_merge($this->options, $options); } - $this->handler = new \Memcache; + $this->handler = new \Memcache(); // 支持集群 $hosts = (array) $this->options['host']; @@ -95,7 +96,7 @@ public function get($name, $default = null): mixed { $result = $this->handler->get($this->getCacheKey($name)); - return false !== $result ? $this->unserialize($result) : $default; + return false !== $result ? $this->unserialize($result, $name, $default) : $default; } /** diff --git a/src/think/cache/driver/Memcached.php b/src/think/cache/driver/Memcached.php index 8299d9c5f2..061f4bd7bc 100644 --- a/src/think/cache/driver/Memcached.php +++ b/src/think/cache/driver/Memcached.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache\driver; @@ -53,7 +54,7 @@ public function __construct(array $options = []) $this->options = array_merge($this->options, $options); } - $this->handler = new \Memcached; + $this->handler = new \Memcached(); if (!empty($this->options['option'])) { $this->handler->setOptions($this->options['option']); @@ -109,7 +110,7 @@ public function get($name, $default = null): mixed { $result = $this->handler->get($this->getCacheKey($name)); - return false !== $result ? $this->unserialize($result) : $default; + return false !== $result ? $this->unserialize($result, $name, $default) : $default; } /** diff --git a/src/think/cache/driver/Redis.php b/src/think/cache/driver/Redis.php index 588cf43658..47e9deb67e 100644 --- a/src/think/cache/driver/Redis.php +++ b/src/think/cache/driver/Redis.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache\driver; @@ -54,7 +55,7 @@ public function handler() { if (!$this->handler) { if (extension_loaded('redis')) { - $this->handler = new \Redis; + $this->handler = new \Redis(); if ($this->options['persistent']) { $this->handler->pconnect($this->options['host'], (int) $this->options['port'], (int) $this->options['timeout'], 'persistent_id_' . $this->options['select']); @@ -120,7 +121,7 @@ public function get($name, $default = null): mixed return $default; } - return $this->unserialize($value); + return $this->unserialize($value, $name, $value); } /** @@ -243,5 +244,5 @@ public function getTagItems($tag): array public function __call($method, $args) { return call_user_func_array([$this->handler(), $method], $args); - } + } } diff --git a/src/think/cache/driver/Wincache.php b/src/think/cache/driver/Wincache.php index 2fdd8bdde0..6c469cb6f0 100644 --- a/src/think/cache/driver/Wincache.php +++ b/src/think/cache/driver/Wincache.php @@ -1,4 +1,5 @@ // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace think\cache\driver; @@ -75,7 +76,7 @@ public function get($name, $default = null): mixed { $key = $this->getCacheKey($name); - return wincache_ucache_exists($key) ? $this->unserialize(wincache_ucache_get($key)) : $default; + return wincache_ucache_exists($key) ? $this->unserialize(wincache_ucache_get($key), $name, $default) : $default; } /** diff --git a/tests/CacheTest.php b/tests/CacheTest.php index 82bae1e5ec..e1c14d6b6c 100644 --- a/tests/CacheTest.php +++ b/tests/CacheTest.php @@ -107,7 +107,6 @@ public function testFileCache() $this->cache->setMultiple(['foo' => ['foobar', 'bar'], 'foobar' => ['foo', 'bar']]); $this->cache->tag('foo')->setMultiple(['foo' => ['foobar', 'bar'], 'foobar' => ['foo', 'bar']]); $this->assertEquals(['foo' => ['foobar', 'bar'], 'foobar' => ['foo', 'bar']], $this->cache->getMultiple(['foo', 'foobar'])); - $this->assertIsInt($this->cache->getWriteTimes()); $this->assertTrue($this->cache->deleteMultiple(['foo', 'foobar'])); } @@ -151,4 +150,26 @@ public function testRedisCache() $this->cache->tag('foo')->set('bar', 'foobar'); $this->cache->tag('foo')->clear(); } + + // 忽略反序列化数据时的异常 + public function testIgnoreUnserializeException() + { + $root = vfsStream::setup(); + + $this->config->shouldReceive('get')->with('cache.default', null)->andReturn('file'); + + $this->config->shouldReceive('get')->with('cache.stores.file', null) + ->andReturn(['type' => 'file', 'path' => $root->url(), 'serialize' => ['serialize', 'unserialize', true]]); + + $this->cache->set('unserializeException', ['name' => 'thinkphp']); + $this->assertEquals(['name' => 'thinkphp'], $this->cache->get('unserializeException')); + + // 篡改缓存文件,使缓存中的序列化数据无效 + $filename = $this->cache->getCacheKey('unserializeException'); + file_put_contents($filename, str_replace('s:8:"thinkphp"', '', file_get_contents($filename))); + $this->assertEquals(['name' => 'thinkphp1'], $this->cache->get('unserializeException', ['name' => 'thinkphp1'])); + + // 序列化数据无效会自动删除缓存 + $this->assertFalse($this->cache->has('unserializeException')); + } }