Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[lock] Prevent user serializing the key when store does not support it. #38395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Lock\Exception;

/**
* UnserializableKeyException is thrown when the key contains state that can no
* be serialized and the user try to serialize it.
* ie. Connection with a database, flock, semaphore, ...
*
* @author Jérémy Derussé <[email protected]>
*/
class UnserializableKeyException extends \RuntimeException implements ExceptionInterface
{
}
17 changes: 17 additions & 0 deletions src/Symfony/Component/Lock/Key.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\Component\Lock;

use Symfony\Component\Lock\Exception\UnserializableKeyException;

/**
* Key is a container for the state of the locks in stores.
*
Expand All @@ -21,6 +23,7 @@ final class Key
private $resource;
private $expiringTime;
private $state = [];
private $serializable = true;

public function __construct(string $resource)
{
Expand Down Expand Up @@ -52,6 +55,11 @@ public function getState(string $stateKey)
return $this->state[$stateKey];
}

public function markUnserializable(): void
{
$this->serializable = false;
}

public function resetLifetime()
{
$this->expiringTime = null;
Expand Down Expand Up @@ -83,4 +91,13 @@ public function isExpired(): bool
{
return null !== $this->expiringTime && $this->expiringTime <= microtime(true);
}

public function __sleep(): array
{
if (!$this->serializable) {
throw new UnserializableKeyException('The key can not be serialized.');
}

return ['resource', 'expiringTime', 'state'];
}
}
1 change: 1 addition & 0 deletions src/Symfony/Component/Lock/Store/FlockStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private function lock(Key $key, bool $read, bool $blocking)
}

$key->setState(__CLASS__, [$read, $handle]);
$key->markUnserializable();
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Lock/Store/SemaphoreStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private function lock(Key $key, bool $blocking)
}

$key->setState(__CLASS__, $resource);
$key->markUnserializable();
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Lock/Store/ZookeeperStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public function save(Key $key)
$token = $this->getUniqueToken($key);

$this->createNewLock($resource, $token);
$key->markUnserializable();

$this->checkNotExpired($key);
}
Expand Down
42 changes: 42 additions & 0 deletions src/Symfony/Component/Lock/Tests/KeyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Lock\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Lock\Exception\UnserializableKeyException;
use Symfony\Component\Lock\Key;

/**
* @author Jérémy Derussé <[email protected]>
*/
class KeyTest extends TestCase
{
public function testSerialize()
{
$key = new Key(__METHOD__);
$key->reduceLifetime(1);
$key->setState('foo', 'bar');

$copy = unserialize(serialize($key));
$this->assertSame($key->getState('foo'), $copy->getState('foo'));
$this->assertEqualsWithDelta($key->getRemainingLifetime(), $copy->getRemainingLifetime(), 0.001);
}

public function testUnserialize()
{
$key = new Key(__METHOD__);
$key->markUnserializable();

$this->expectException(UnserializableKeyException::class);
serialize($key);
}
}
1 change: 1 addition & 0 deletions src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class FlockStoreTest extends AbstractStoreTest
{
use BlockingStoreTestTrait;
use SharedLockStoreTestTrait;
use UnserializableTestTrait;

/**
* {@inheritdoc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
class SemaphoreStoreTest extends AbstractStoreTest
{
use BlockingStoreTestTrait;
use UnserializableTestTrait;

/**
* {@inheritdoc}
Expand Down
42 changes: 42 additions & 0 deletions src/Symfony/Component/Lock/Tests/Store/UnserializableTestTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Lock\Tests\Store;

use Symfony\Component\Lock\Exception\UnserializableKeyException;
use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\PersistingStoreInterface;

/**
* @author Jérémy Derussé <[email protected]>
*/
trait UnserializableTestTrait
{
/**
* @see AbstractStoreTest::getStore()
*
* @return PersistingStoreInterface
*/
abstract protected function getStore();

public function testUnserializableKey()
{
$store = $this->getStore();

$key = new Key(uniqid(__METHOD__, true));

$store->save($key);
$this->assertTrue($store->exists($key));

$this->expectException(UnserializableKeyException::class);
serialize($key);
}
}
2 changes: 2 additions & 0 deletions src/Symfony/Component/Lock/Tests/Store/ZookeeperStoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*/
class ZookeeperStoreTest extends AbstractStoreTest
{
use UnserializableTestTrait;

/**
* @return ZookeeperStore
*/
Expand Down