8000 bug #46143 [Cache] Prevent fatal errors on php 8 when running concurr… · symfony/symfony@ff578de · GitHub
[go: up one dir, main page]

Skip to content

Commit ff578de

Browse files
bug #46143 [Cache] Prevent fatal errors on php 8 when running concurrently with TagAwareAdapter v6.1 (sbelyshkin)
This PR was squashed before being merged into the 4.4 branch. Discussion ---------- [Cache] Prevent fatal errors on php 8 when running concurrently with TagAwareAdapter v6.1 | Q | A | ------------- | --- | Branch? | 4.4 - 5.3 | Bug fix? | no | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | - <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT | Doc PR | This fix prevents fatal errors which may arise during rolling updates when TagAwareAdapter is upgraded from versions prior to 5.4 to the latest 6.1. TypeErrors occur because of different value types for tag versions and rules for numeric strings in php 8.x https://www.php.net/manual/en/language.types.numeric-strings.php <!-- Replace this notice by a short README for your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too.) - Features and deprecations must be submitted against the latest branch. - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> Commits ------- 33f8496 [Cache] Prevent fatal errors on php 8 when running concurrently with TagAwareAdapter v6.1
2 parents f0ffa47 + 33f8496 commit ff578de

File tree

2 files changed

+118
-6
lines changed

2 files changed

+118
-6
lines changed

src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,11 @@ public function hasItem($key)
177177
}
178178

179179
foreach ($this->getTagVersions([$itemTags]) as $tag => $version) {
180-
if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) {
181-
return false;
180+
if ($itemTags[$tag] === $version || \is_int($itemTags[$tag]) && \is_int($version) && 1 === $itemTags[$tag] - $version) {
181+
continue;
182182
}
183+
184+
return false;
183185
}
184186

185187
return true;
@@ -366,10 +368,11 @@ private function generateItems(iterable $items, array $tagKeys)
366368

367369
foreach ($itemTags as $key => $tags) {
368370
foreach ($tags as $tag => $version) {
369-
if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) {
370-
unset($itemTags[$key]);
371-
continue 2;
371+
if ($tagVersions[$tag] === $version || \is_int($version) && \is_int($tagVersions[$tag]) && 1 === $version - $tagVersions[$tag]) {
372+
continue;
372373
}
374+
unset($itemTags[$key]);
375+
continue 2;
373376
}
374377
}
375378
$tagVersions = $tagKeys = null;
@@ -408,7 +411,7 @@ private function getTagVersions(array $tagsByKey, array &$invalidatedTags = [])
408411
$tags = [];
409412
foreach ($tagVersions as $tag => $version) {
410413
$tags[$tag.static::TAGS_PREFIX] = $tag;
411-
if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) {
414+
if ($fetchTagVersions || !isset($this->knownTagVersions[$tag]) || !\is_int($version)) {
412415
$fetchTagVersions = true;
413416
continue;
414417
}
@@ -430,6 +433,10 @@ private function getTagVersions(array $tagsByKey, array &$invalidatedTags = [])
430433
if (isset($invalidatedTags[$tag])) {
431434
$invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]);
432435
}
436+
if (!\is_int($tagVersions[$tag])) {
437+
unset($this->knownTagVersions[$tag]);
438+
continue;
439+
}
433440
$this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]];
434441
}
435442

src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,109 @@ private function getNonPruneableMock(): AdapterInterface
234234
{
235235
return $this->createMock(AdapterInterface::class);
236236
}
237+
238+
/**
239+
* @doesNotPerformAssertions
240+
*/
241+
public function testToleranceForStringsAsTagVersionsCase1()
242+
{
243+
$pool = $this->createCachePool();
244+
$adapter = new FilesystemAdapter();
245+
246+
$itemKey = 'foo';
247+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
248+
$adapter->save($tag->set("\x00abc\xff"));
249+
$item = $pool->getItem($itemKey);
250+
$pool->save($item->tag('bar'));
251+
$pool->hasItem($itemKey);
252+
$pool->getItem($itemKey);
253+
}
254+
255+
/**
256+
* @doesNotPerformAssertions
257+
*/
258+
public function testToleranceForStringsAsTagVersionsCase2()
259+
{
260+
$pool = $this->createCachePool();
261+
$adapter = new FilesystemAdapter();
262+
263+
$itemKey = 'foo';
264+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
265+
$adapter->save($tag->set("\x00abc\xff"));
266+
$item = $pool->getItem($itemKey);
267+
$pool->save($item->tag('bar'));
268+
sleep(100);
269+
$pool->getItem($itemKey);
270+
$pool->hasItem($itemKey);
271+
}
272+
273+
/**
274+
* @doesNotPerformAssertions
275+
*/
276+
public function testToleranceForStringsAsTagVersionsCase3()
277+
{
278+
$pool = $this->createCachePool();
279+
$adapter = new FilesystemAdapter();
280+
281+
$itemKey = 'foo';
282+
$adapter->deleteItem('bar'.TagAwareAdapter::TAGS_PREFIX);
283+
$item = $pool->getItem($itemKey);
284+
$pool->save($item->tag('bar'));
285+
$pool->getItem($itemKey);
286+
287+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
288+
$adapter->save($tag->set("\x00abc\xff"));
289+
290+
$pool->hasItem($itemKey);
291+
$pool->getItem($itemKey);
292+
sleep(100);
293+
$pool->getItem($itemKey);
294+
$pool->hasItem($itemKey);
295+
}
296+
297+
/**
298+
* @doesNotPerformAssertions
299+
*/
300+
public function testToleranceForStringsAsTagVersionsCase4()
301+
{
302+
$pool = $this->createCachePool();
303+
$adapter = new FilesystemAdapter();
304+
305+
$itemKey = 'foo';
306+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
307+
$adapter->save($tag->set('abcABC'));
308+
309+
$item = $pool->getItem($itemKey);
310+
$pool->save($item->tag('bar'));
311+
312+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
313+
$adapter->save($tag->set('001122'));
314+
315+
$pool->invalidateTags(['bar']);
316+
$pool->getItem($itemKey);
317+
}
318+
319+
/**
320+
* @doesNotPerformAssertions
321+
*/
322+
public function testToleranceForStringsAsTagVersionsCase5()
323+
{
324+
$pool = $this->createCachePool();
325+
$pool2 = $this->createCachePool();
326+
$adapter = new FilesystemAdapter();
327+
328+
$itemKey1 = 'foo';
329+
$item = $pool->getItem($itemKey1);
330+
$pool->save($item->tag('bar'));
331+
332+
$tag = $adapter->getItem('bar'.TagAwareAdapter::TAGS_PREFIX);
333+
$adapter->save($tag->set('abcABC'));
334+
335+
$itemKey2 = 'baz';
336+
$item = $pool2->getItem($itemKey2);
337+
$pool2->save($item->tag('bar'));
338+
foreach ($pool->getItems([$itemKey1, $itemKey2]) as $item) {
339+
// run generator
340+
}
341+
}
237342
}

0 commit comments

Comments
 (0)
0