From 0420306075cce705a43e1c738ae0aed4145121e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 5 Jul 2024 15:41:14 +0200 Subject: [PATCH 1/2] misc: Replace `sha1()` by `hash('sha1', ...)` The dedicated `sha1()` function is proposed for deprecation with PHP 8.4: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_md5_sha1_md5_file_and_sha1_file For a future change it might also be considered to move to a cheaper hash function. The xxHash family (available as `xxh*`) is faster and should be sufficiently collision resistant for use within the cache. --- src/Cache/KeySanitizerCache.php | 6 +++--- .../Repository/Cache/CacheClassDefinitionRepository.php | 4 ++-- .../Repository/Cache/CacheFunctionDefinitionRepository.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Cache/KeySanitizerCache.php b/src/Cache/KeySanitizerCache.php index d0518e98..0d3785c6 100644 --- a/src/Cache/KeySanitizerCache.php +++ b/src/Cache/KeySanitizerCache.php @@ -9,7 +9,7 @@ use Psr\SimpleCache\CacheInterface; use Traversable; -use function sha1; +use function hash; /** * @internal @@ -32,10 +32,10 @@ public function __construct( // 1. We append the current version of the package to the cache key in // order to avoid collisions between entries from different versions // of the library. - // 2. The key is sha1'd so that it does not contain illegal characters. + // 2. The key is hashed so that it does not contain illegal characters. // @see https://www.php-fig.org/psr/psr-16/#12-definitions // @infection-ignore-all - $this->sanitize = static fn (string $key) => $key . sha1(self::$version ??= PHP_VERSION . '/' . Package::version()); + $this->sanitize = static fn (string $key) => $key . hash('sha1', self::$version ??= PHP_VERSION . '/' . Package::version()); } public function warmup(): void diff --git a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php index c23cdfa8..c0992bad 100644 --- a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php @@ -9,7 +9,7 @@ use CuyZ\Valinor\Type\ObjectType; use Psr\SimpleCache\CacheInterface; -use function sha1; +use function hash; /** @internal */ final class CacheClassDefinitionRepository implements ClassDefinitionRepository @@ -23,7 +23,7 @@ public function __construct( public function for(ObjectType $type): ClassDefinition { // @infection-ignore-all - $key = 'class-definition' . sha1($type->toString()); + $key = 'class-definition' . hash('sha1', $type->toString()); $entry = $this->cache->get($key); diff --git a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php index 93a24be2..b56b729b 100644 --- a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php @@ -9,7 +9,7 @@ use CuyZ\Valinor\Utility\Reflection\Reflection; use Psr\SimpleCache\CacheInterface; -use function sha1; +use function hash; /** @internal */ final class CacheFunctionDefinitionRepository implements FunctionDefinitionRepository @@ -25,7 +25,7 @@ public function for(callable $function): FunctionDefinition $reflection = Reflection::function($function); // @infection-ignore-all - $key = 'function-definition-' . sha1($reflection->getFileName() . $reflection->getStartLine() . $reflection->getEndLine()); + $key = 'function-definition-' . hash('sha1', $reflection->getFileName() . $reflection->getStartLine() . $reflection->getEndLine()); $entry = $this->cache->get($key); From 356821e2a4548898f30bb8a86d494080aec3dca1 Mon Sep 17 00:00:00 2001 From: Romain Canon Date: Wed, 18 Sep 2024 08:41:28 +0200 Subject: [PATCH 2/2] misc: use `xxh128` hash for cache keys --- src/Cache/KeySanitizerCache.php | 47 +++++++++++-------- .../Cache/CacheClassDefinitionRepository.php | 4 +- .../CacheFunctionDefinitionRepository.php | 4 +- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/Cache/KeySanitizerCache.php b/src/Cache/KeySanitizerCache.php index 0d3785c6..0f78ca25 100644 --- a/src/Cache/KeySanitizerCache.php +++ b/src/Cache/KeySanitizerCache.php @@ -4,12 +4,12 @@ namespace CuyZ\Valinor\Cache; -use Closure; use CuyZ\Valinor\Utility\Package; use Psr\SimpleCache\CacheInterface; use Traversable; use function hash; +use function strstr; /** * @internal @@ -21,21 +21,28 @@ final class KeySanitizerCache implements WarmupCache { private static string $version; - /** @var Closure(string): string */ - private Closure $sanitize; - public function __construct( /** @var CacheInterface */ private CacheInterface $delegate - ) { - // Two things: - // 1. We append the current version of the package to the cache key in - // order to avoid collisions between entries from different versions - // of the library. - // 2. The key is hashed so that it does not contain illegal characters. - // @see https://www.php-fig.org/psr/psr-16/#12-definitions - // @infection-ignore-all - $this->sanitize = static fn (string $key) => $key . hash('sha1', self::$version ??= PHP_VERSION . '/' . Package::version()); + ) {} + + /** + * Two things: + * 1. We append the current version of the package to the cache key in order + * to avoid collisions between entries from different versions of the + * library. + * 2. The key is hashed so that it does not contain illegal characters. + * @see https://www.php-fig.org/psr/psr-16/#12-definitions + * + * @infection-ignore-all + */ + private function sanitize(string $key): string + { + self::$version ??= PHP_VERSION . '/' . Package::version(); + + $firstPart = strstr($key, "\0", before_needle: true); + + return $firstPart . hash('xxh128', $key . self::$version); } public function warmup(): void @@ -47,17 +54,17 @@ public function warmup(): void public function get($key, $default = null): mixed { - return $this->delegate->get(($this->sanitize)($key), $default); + return $this->delegate->get($this->sanitize($key), $default); } public function set($key, $value, $ttl = null): bool { - return $this->delegate->set(($this->sanitize)($key), $value, $ttl); + return $this->delegate->set($this->sanitize($key), $value, $ttl); } public function delete($key): bool { - return $this->delegate->delete(($this->sanitize)($key)); + return $this->delegate->delete($this->sanitize($key)); } public function clear(): bool @@ -67,7 +74,7 @@ public function clear(): bool public function has($key): bool { - return $this->delegate->has(($this->sanitize)($key)); + return $this->delegate->has($this->sanitize($key)); } /** @@ -76,7 +83,7 @@ public function has($key): bool public function getMultiple($keys, $default = null): Traversable { foreach ($keys as $key) { - yield $key => $this->delegate->get(($this->sanitize)($key), $default); + yield $key => $this->delegate->get($this->sanitize($key), $default); } } @@ -85,7 +92,7 @@ public function setMultiple($values, $ttl = null): bool $versionedValues = []; foreach ($values as $key => $value) { - $versionedValues[($this->sanitize)($key)] = $value; + $versionedValues[$this->sanitize($key)] = $value; } return $this->delegate->setMultiple($versionedValues, $ttl); @@ -96,7 +103,7 @@ public function deleteMultiple($keys): bool $transformedKeys = []; foreach ($keys as $key) { - $transformedKeys[] = ($this->sanitize)($key); + $transformedKeys[] = $this->sanitize($key); } return $this->delegate->deleteMultiple($transformedKeys); diff --git a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php index c0992bad..89a720e4 100644 --- a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php @@ -9,8 +9,6 @@ use CuyZ\Valinor\Type\ObjectType; use Psr\SimpleCache\CacheInterface; -use function hash; - /** @internal */ final class CacheClassDefinitionRepository implements ClassDefinitionRepository { @@ -23,7 +21,7 @@ public function __construct( public function for(ObjectType $type): ClassDefinition { // @infection-ignore-all - $key = 'class-definition' . hash('sha1', $type->toString()); + $key = "class-definition-\0" . $type->toString(); $entry = $this->cache->get($key); diff --git a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php index b56b729b..265b8189 100644 --- a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php @@ -9,8 +9,6 @@ use CuyZ\Valinor\Utility\Reflection\Reflection; use Psr\SimpleCache\CacheInterface; -use function hash; - /** @internal */ final class CacheFunctionDefinitionRepository implements FunctionDefinitionRepository { @@ -25,7 +23,7 @@ public function for(callable $function): FunctionDefinition $reflection = Reflection::function($function); // @infection-ignore-all - $key = 'function-definition-' . hash('sha1', $reflection->getFileName() . $reflection->getStartLine() . $reflection->getEndLine()); + $key = "function-definition-\0" . $reflection->getFileName() . ':' . $reflection->getStartLine() . '-' . $reflection->getEndLine(); $entry = $this->cache->get($key);