Skip to content

Commit fb131c1

Browse files
authored
Merge pull request #50436 from nextcloud/fix/encoding-wrapper-scanner
fix: Harden files scanner for invalid null access
2 parents e40b635 + b48ee2e commit fb131c1

File tree

12 files changed

+186
-197
lines changed

12 files changed

+186
-197
lines changed

apps/files_sharing/lib/Cache.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ protected function getRoot() {
6363
/** @var Jail $currentStorage */
6464
$absoluteRoot = $currentStorage->getJailedPath($absoluteRoot);
6565
}
66-
$this->root = $absoluteRoot;
66+
$this->root = $absoluteRoot ?? '';
6767
}
6868
return $this->root;
6969
}
7070

71-
protected function getGetUnjailedRoot() {
71+
protected function getGetUnjailedRoot(): string {
7272
return $this->sourceRootInfo->getPath();
7373
}
7474

apps/files_sharing/lib/External/Scanner.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $loc
2929
* @param string $file file to scan
3030
* @param int $reuseExisting
3131
* @param int $parentId
32-
* @param array | null $cacheData existing data in the cache for the file to be scanned
32+
* @param \OC\Files\Cache\CacheEntry|array|null|false $cacheData existing data in the cache for the file to be scanned
3333
* @param bool $lock set to false to disable getting an additional read lock during scanning
34-
* @return array | null an array of metadata of the scanned file
34+
* @param array|null $data the metadata for the file, as returned by the storage
35+
* @return array|null an array of metadata of the scanned file
3536
*/
3637
public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) {
3738
try {

apps/files_sharing/lib/Scanner.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
5757
$sourceScanner = $this->getSourceScanner();
5858
if ($sourceScanner instanceof ObjectStoreScanner) {
5959
// ObjectStoreScanner doesn't scan
60-
return [];
60+
return null;
6161
} else {
6262
return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock);
6363
}

build/psalm-baseline.xml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -873,11 +873,6 @@
873873
<code><![CDATA[Mount]]></code>
874874
</MoreSpecificReturnType>
875875
</file>
876-
<file src="apps/files_sharing/lib/External/Scanner.php">
877-
<MoreSpecificImplementedParamType>
878-
<code><![CDATA[$cacheData]]></code>
879-
</MoreSpecificImplementedParamType>
880-
</file>
881876
<file src="apps/files_sharing/lib/MountProvider.php">
882877
<RedundantFunctionCall>
883878
<code><![CDATA[array_values]]></code>
@@ -1758,14 +1753,10 @@
17581753
</MoreSpecificReturnType>
17591754
</file>
17601755
<file src="lib/private/Files/Cache/Cache.php">
1761-
<InvalidArgument>
1762-
<code><![CDATA[$parentData]]></code>
1763-
</InvalidArgument>
17641756
<InvalidNullableReturnType>
17651757
<code><![CDATA[array]]></code>
17661758
</InvalidNullableReturnType>
17671759
<InvalidScalarArgument>
1768-
<code><![CDATA[$path]]></code>
17691760
<code><![CDATA[\OC_Util::normalizeUnicode($path)]]></code>
17701761
</InvalidScalarArgument>
17711762
<NullableReturnStatement>
@@ -1796,12 +1787,6 @@
17961787
<InvalidArgument>
17971788
<code><![CDATA[self::SCAN_RECURSIVE_INCOMPLETE]]></code>
17981789
</InvalidArgument>
1799-
<InvalidReturnStatement>
1800-
<code><![CDATA[$existingChildren]]></code>
1801-
</InvalidReturnStatement>
1802-
<InvalidReturnType>
1803-
<code><![CDATA[array[]]]></code>
1804-
</InvalidReturnType>
18051790
</file>
18061791
<file src="lib/private/Files/Cache/Storage.php">
18071792
<InvalidNullableReturnType>

lib/private/Files/Cache/Cache.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function getNumericStorageId() {
109109
/**
110110
* get the stored metadata of a file or folder
111111
*
112-
* @param string | int $file either the path of a file or folder or the file id for a file or folder
112+
* @param string|int $file either the path of a file or folder or the file id for a file or folder
113113
* @return ICacheEntry|false the cache entry as array or false if the file is not found in the cache
114114
*/
115115
public function get($file) {
@@ -131,15 +131,17 @@ public function get($file) {
131131
$data = $result->fetch();
132132
$result->closeCursor();
133133

134-
//merge partial data
135-
if (!$data && is_string($file) && isset($this->partial[$file])) {
136-
return $this->partial[$file];
137-
} elseif (!$data) {
138-
return $data;
139-
} else {
134+
if ($data !== false) {
140135
$data['metadata'] = $metadataQuery->extractMetadata($data)->asArray();
141136
return self::cacheEntryFromData($data, $this->mimetypeLoader);
137+
} else {
138+
//merge partial data
139+
if (is_string($file) && isset($this->partial[$file])) {
140+
return $this->partial[$file];
141+
}
142142
}
143+
144+
return false;
143145
}
144146

145147
/**
@@ -886,19 +888,23 @@ public function searchQuery(ISearchQuery $query) {
886888
/**
887889
* Re-calculate the folder size and the size of all parent folders
888890
*
889-
* @param string|boolean $path
890-
* @param array $data (optional) meta data of the folder
891+
* @param array|ICacheEntry|null $data (optional) meta data of the folder
891892
*/
892-
public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
893+
public function correctFolderSize(string $path, $data = null, bool $isBackgroundScan = false): void {
893894
$this->calculateFolderSize($path, $data);
895+
894896
if ($path !== '') {
895897
$parent = dirname($path);
896898
if ($parent === '.' || $parent === '/') {
897899
$parent = '';
898900
}
901+
899902
if ($isBackgroundScan) {
900903
$parentData = $this->get($parent);
901-
if ($parentData['size'] !== -1 && $this->getIncompleteChildrenCount($parentData['fileid']) === 0) {
904+
if ($parentData !== false
905+
&& $parentData['size'] !== -1
906+
&& $this->getIncompleteChildrenCount($parentData['fileid']) === 0
907+
) {
902908
$this->correctFolderSize($parent, $parentData, $isBackgroundScan);
903909
}
904910
} else {
@@ -1009,8 +1015,8 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i
10091015
}
10101016

10111017
// only set unencrypted size for a folder if any child entries have it set, or the folder is empty
1012-
$shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || $entry['unencrypted_size'] > 0;
1013-
if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) {
1018+
$shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || ($entry['unencrypted_size'] ?? 0) > 0;
1019+
if ($entry['size'] !== $totalSize || (($entry['unencrypted_size'] ?? 0) !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) {
10141020
if ($shouldWriteUnEncryptedSize) {
10151021
// if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes
10161022
if ($unencryptedMax === 0) {

0 commit comments

Comments
 (0)