From dac253c0a31e9de8cd96497fdeb0152bb829994f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 14 Nov 2025 13:23:20 +0100 Subject: [PATCH] feat(profiler): Use gzdecode/gzencode to parse profiles See https://github.com/symfony/symfony/blob/42a80727f9220f9cac78379005629cdf753a62b1/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php#L299 Signed-off-by: Carl Schwan --- lib/private/Profiler/FileProfilerStorage.php | 52 +++++++++++++++----- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/private/Profiler/FileProfilerStorage.php b/lib/private/Profiler/FileProfilerStorage.php index c690fcd52d118..4fa056b0009cc 100644 --- a/lib/private/Profiler/FileProfilerStorage.php +++ b/lib/private/Profiler/FileProfilerStorage.php @@ -17,6 +17,17 @@ class FileProfilerStorage { // Folder where profiler data are stored. private string $folder; + /** @psalm-suppress UndefinedClass */ + public const allowedClasses = [ + \OCA\Profiler\DataCollector\EventLoggerDataProvider::class, + \OCA\Profiler\DataCollector\HttpDataCollector::class, + \OCA\Profiler\DataCollector\MemoryDataCollector::class, + \OCA\User_LDAP\DataCollector\LdapDataCollector::class, + \OC\Memcache\ProfilerWrapperCache::class, + \OC\Profiler\RoutingDataCollector::class, + \OC\DB\DbDataCollector::class, + ]; + /** * Constructs the file storage using a "dsn-like" path. * @@ -97,11 +108,21 @@ public function read(string $token): ?IProfile { return null; } - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://' . $file; + $h = fopen($file, 'r'); + flock($h, \LOCK_SH); + $data = stream_get_contents($h); + flock($h, \LOCK_UN); + fclose($h); + + if (\function_exists('gzdecode')) { + $data = @gzdecode($data) ?: $data; + } + + if (!$data = unserialize($data, ['allowed_classes' => self::allowedClasses])) { + return null; } - return $this->createProfileFromData($token, unserialize(file_get_contents($file))); + return $this->createProfileFromData($token, $data); } /** @@ -139,14 +160,13 @@ public function write(IProfile $profile): bool { 'status_code' => $profile->getStatusCode(), ]; - $context = stream_context_create(); + $data = serialize($data); - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://' . $file; - stream_context_set_option($context, 'zlib', 'level', 3); + if (\function_exists('gzencode')) { + $data = gzencode($data, 3); } - if (file_put_contents($file, serialize($data), 0, $context) === false) { + if (file_put_contents($file, $data, \LOCK_EX) === false) { return false; } @@ -266,11 +286,21 @@ protected function createProfileFromData(string $token, array $data, ?IProfile $ continue; } - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://' . $file; + $h = fopen($file, 'r'); + flock($h, \LOCK_SH); + $data = stream_get_contents($h); + flock($h, \LOCK_UN); + fclose($h); + + if (\function_exists('gzdecode')) { + $data = @gzdecode($data) ?: $data; + } + + if (!$data = unserialize($data, ['allowed_classes' => self::allowedClasses])) { + continue; } - $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); + $profile->addChild($this->createProfileFromData($token, $data, $profile)); } return $profile;