Skip to content

Commit 5c7f5b4

Browse files
authored
Merge pull request #47776 from nextcloud/backport/47769/stable28
[stable28] fix: Use sha256 to hash arguments of background jobs
2 parents 257a9da + 095389d commit 5c7f5b4

4 files changed

Lines changed: 85 additions & 5 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OC\Core\Migrations;
11+
12+
use Closure;
13+
use OCP\DB\ISchemaWrapper;
14+
use OCP\DB\QueryBuilder\IQueryBuilder;
15+
use OCP\IDBConnection;
16+
use OCP\Migration\IOutput;
17+
use OCP\Migration\SimpleMigrationStep;
18+
19+
/**
20+
* Migrate the argument_hash column of oc_jobs to use sha256 instead of md5.
21+
*/
22+
class Version28000Date20240828142927 extends SimpleMigrationStep {
23+
public function __construct(
24+
protected IDBConnection $connection,
25+
) {
26+
}
27+
28+
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
29+
/** @var ISchemaWrapper $schema */
30+
$schema = $schemaClosure();
31+
32+
// Increase the column size from 32 to 64
33+
$table = $schema->getTable('jobs');
34+
$table->modifyColumn('argument_hash', [
35+
'notnull' => false,
36+
'length' => 64,
37+
]);
38+
39+
return $schema;
40+
}
41+
42+
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
43+
$chunkSize = 1000;
44+
$offset = 0;
45+
$nullHash = hash('sha256', 'null');
46+
47+
$selectQuery = $this->connection->getQueryBuilder()
48+
->select('*')
49+
->from('jobs')
50+
->setMaxResults($chunkSize);
51+
52+
$insertQuery = $this->connection->getQueryBuilder();
53+
$insertQuery->update('jobs')
54+
->set('argument_hash', $insertQuery->createParameter('argument_hash'))
55+
->where($insertQuery->expr()->eq('id', $insertQuery->createParameter('id')));
56+
57+
do {
58+
$result = $selectQuery
59+
->setFirstResult($offset)
60+
->executeQuery();
61+
62+
$jobs = $result->fetchAll();
63+
$count = count($jobs);
64+
65+
foreach ($jobs as $jobRow) {
66+
if ($jobRow['argument'] === 'null') {
67+
$hash = $nullHash;
68+
} else {
69+
$hash = hash('sha256', $jobRow['argument']);
70+
}
71+
$insertQuery->setParameter('id', (string)$jobRow['id'], IQueryBuilder::PARAM_INT);
72+
$insertQuery->setParameter('argument_hash', $hash);
73+
$insertQuery->executeStatement();
74+
}
75+
76+
$offset += $chunkSize;
77+
} while ($count === $chunkSize);
78+
}
79+
}

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,7 @@
12321232
'OC\\Core\\Migrations\\Version28000Date20231004103301' => $baseDir . '/core/Migrations/Version28000Date20231004103301.php',
12331233
'OC\\Core\\Migrations\\Version28000Date20231103104802' => $baseDir . '/core/Migrations/Version28000Date20231103104802.php',
12341234
'OC\\Core\\Migrations\\Version28000Date20231126110901' => $baseDir . '/core/Migrations/Version28000Date20231126110901.php',
1235+
'OC\\Core\\Migrations\\Version28000Date20240828142927' => $baseDir . '/core/Migrations/Version28000Date20240828142927.php',
12351236
'OC\\Core\\Migrations\\Version30000Date20240814180800' => $baseDir . '/core/Migrations/Version30000Date20240814180800.php',
12361237
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
12371238
'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
12651265
'OC\\Core\\Migrations\\Version28000Date20231004103301' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20231004103301.php',
12661266
'OC\\Core\\Migrations\\Version28000Date20231103104802' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20231103104802.php',
12671267
'OC\\Core\\Migrations\\Version28000Date20231126110901' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20231126110901.php',
1268+
'OC\\Core\\Migrations\\Version28000Date20240828142927' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20240828142927.php',
12681269
'OC\\Core\\Migrations\\Version30000Date20240814180800' => __DIR__ . '/../../..' . '/core/Migrations/Version30000Date20240814180800.php',
12691270
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
12701271
'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php',

lib/private/BackgroundJob/JobList.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
use Psr\Log\LoggerInterface;
4444
use function get_class;
4545
use function json_encode;
46-
use function md5;
4746
use function strlen;
4847

4948
class JobList implements IJobList {
@@ -80,7 +79,7 @@ public function add($job, $argument = null, int $firstCheck = null): void {
8079
->values([
8180
'class' => $query->createNamedParameter($class),
8281
'argument' => $query->createNamedParameter($argumentJson),
83-
'argument_hash' => $query->createNamedParameter(md5($argumentJson)),
82+
'argument_hash' => $query->createNamedParameter(hash('sha256', $argumentJson)),
8483
'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
8584
'last_checked' => $query->createNamedParameter($firstCheck, IQueryBuilder::PARAM_INT),
8685
]);
@@ -90,7 +89,7 @@ public function add($job, $argument = null, int $firstCheck = null): void {
9089
->set('last_checked', $query->createNamedParameter($firstCheck, IQueryBuilder::PARAM_INT))
9190
->set('last_run', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))
9291
->where($query->expr()->eq('class', $query->createNamedParameter($class)))
93-
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argumentJson))));
92+
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(hash('sha256', $argumentJson))));
9493
}
9594
$query->executeStatement();
9695
}
@@ -115,7 +114,7 @@ public function remove($job, $argument = null): void {
115114
->where($query->expr()->eq('class', $query->createNamedParameter($class)));
116115
if (!is_null($argument)) {
117116
$argumentJson = json_encode($argument);
118-
$query->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argumentJson))));
117+
$query->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(hash('sha256', $argumentJson))));
119118
}
120119

121120
// Add galera safe delete chunking if using mysql
@@ -160,7 +159,7 @@ public function has($job, $argument): bool {
160159
$query->select('id')
161160
->from('jobs')
162161
->where($query->expr()->eq('class', $query->createNamedParameter($class)))
163-
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argument))))
162+
->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(hash('sha256', $argument))))
164163
->setMaxResults(1);
165164

166165
$result = $query->executeQuery();

0 commit comments

Comments
 (0)