Skip to content

Commit

Permalink
FileCache: rebuild cache file before touch when different file owner (y…
Browse files Browse the repository at this point in the history
…iisoft#16120)

* Test Travis envs

* The fix

* posix_geteuid only exists on Linux

* Added PR to changelog
  • Loading branch information
Slamdunk authored and SilverFire committed Apr 22, 2018
1 parent 009682c commit 4f41d11
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ env:
- TASK_TESTS_PHP=1
- TASK_TESTS_JS=0
- TASK_TESTS_COVERAGE=0
- TRAVIS_SECOND_USER=travis_two


services:
Expand Down Expand Up @@ -147,6 +148,9 @@ install:
travis_retry npm install
fi
# Needed for FileCacheTest
- sudo useradd $TRAVIS_SECOND_USER --gid $(id -g) -M

before_script:
#
# Disable:
Expand Down
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Yii Framework 2 Change Log
- Bug #15988: Fixed bash completion (alekciy)
- Bug #15117: Fixed `yii\db\Schema::getTableMetadata` cache refreshing (boboldehampsink)
- Bug #16073: Fixed regression in Oracle `IN` condition builder for more than 1000 items (cebe)
- Bug #16120: FileCache: rebuild cache file before touch when different file owner (Slamdunk)


2.0.15.1 March 21, 2018
Expand Down
6 changes: 6 additions & 0 deletions framework/caching/FileCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ protected function setValue($key, $value, $duration)
if ($this->directoryLevel > 0) {
@FileHelper::createDirectory(dirname($cacheFile), $this->dirMode, true);
}
// If ownership differs the touch call will fail, so we try to
// rebuild the file from scratch by deleting it first
// https://github.com/yiisoft/yii2/pull/16120
if (is_file($cacheFile) && function_exists('posix_geteuid') && fileowner($cacheFile) !== posix_geteuid()) {
@unlink($cacheFile);
}
if (@file_put_contents($cacheFile, $value, LOCK_EX) !== false) {
if ($this->fileMode !== null) {
@chmod($cacheFile, $this->fileMode);
Expand Down
35 changes: 35 additions & 0 deletions tests/framework/caching/FileCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,39 @@ public function testExpireAdd()
static::$time++;
$this->assertFalse($cache->get('expire_testa'));
}

public function testCacheRenewalOnDifferentOwnership()
{
$TRAVIS_SECOND_USER = getenv('TRAVIS_SECOND_USER');
if (empty($TRAVIS_SECOND_USER)) {
$this->markTestSkipped('Travis second user not found');
}

$cache = $this->getCacheInstance();

$cacheValue = uniqid('value_');
$cachePublicKey = uniqid('key_');
$cacheInternalKey = $cache->buildKey($cachePublicKey);

static::$time = \time();
$this->assertTrue($cache->set($cachePublicKey, $cacheValue, 2));
$this->assertSame($cacheValue, $cache->get($cachePublicKey));

$refClass = new \ReflectionClass($cache);
$refMethodGetCacheFile = $refClass->getMethod('getCacheFile');
$refMethodGetCacheFile->setAccessible(true);
$cacheFile = $refMethodGetCacheFile->invoke($cache, $cacheInternalKey);
$refMethodGetCacheFile->setAccessible(false);

$output = array();
$returnVar = null;
exec(sprintf('sudo chown %s %s',
escapeshellarg($TRAVIS_SECOND_USER),
escapeshellarg($cacheFile)
), $output, $returnVar);

$this->assertSame(0, $returnVar, 'Cannot change ownership of cache file to test cache renewal');

$this->assertTrue($cache->set($cachePublicKey, uniqid('value_2_'), 2), 'Cannot rebuild cache on different file ownership');
}
}

0 comments on commit 4f41d11

Please sign in to comment.