Skip to content

Compute hashes of executable files when migrating #2631

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 3 commits into from
Aug 5, 2024
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
15 changes: 6 additions & 9 deletions webapp/migrations/Version20210407120356.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public function up(Schema $schema) : void
for ($idx = 0; $idx < $zip->numFiles; $idx++) {
$filename = basename($zip->getNameIndex($idx));
$content = $zip->getFromIndex($idx);
$encodedContent = ($content === '' ? '' : ('0x' . strtoupper(bin2hex($content))));

// In doubt make files executable, but try to read it from the zip file.
$executableBit = '1';
Expand All @@ -52,21 +51,19 @@ public function up(Schema $schema) : void
$executableBit = '0';
}
$this->connection->executeStatement(
'INSERT INTO executable_file '
. '(`immutable_execid`, `filename`, `ranknumber`, `file_content`, `is_executable`) '
. 'VALUES (' . $immutable_execid . ', "' . $filename . '", '
. $idx . ', ' . $encodedContent . ', '
. $executableBit . ')'
'INSERT INTO executable_file (`immutable_execid`, `filename`, `ranknumber`, `file_content`, `hash`, `is_executable`)'
. ' VALUES (?, ?, ?, ?, ?, ?)',
[$immutable_execid, $filename, $idx, $content, md5($content), $executableBit]
);
}

$this->connection->executeStatement(
'UPDATE executable SET immutable_execid = '
. $immutable_execid . ' WHERE execid = "' . $oldRow['execid'] . '"'
'UPDATE executable SET immutable_execid = :immutable_execid WHERE execid = :execid',
['immutable_execid' => $immutable_execid, 'execid' => $oldRow['execid']]
);
}

$this->addSql('ALTER TABLE `executable` DROP COLUMN `zipfile`');
$this->connection->executeStatement('ALTER TABLE `executable` DROP COLUMN `zipfile`');
}
}

Expand Down
36 changes: 8 additions & 28 deletions webapp/migrations/Version20230508163415.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,28 @@

namespace DoctrineMigrations;

use App\Entity\ExecutableFile;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230508163415 extends AbstractMigration
{
// The code that was in this file was moved to Version20230508180000.php so
// that it will re-run after Version20230508170000.php. This file has been
// kept as a no-op to prevent warnings about previously executed migrations
// that are not registered.

public function getDescription(): string
{
return 'Update hashes of immutable executables';
return '[Deleted]';
}

public function up(Schema $schema): void
{
$immutableExecutables = $this->connection->fetchAllAssociative('SELECT immutable_execid FROM immutable_executable');
foreach ($immutableExecutables as $immutableExecutable) {
$files = $this->connection->fetchAllAssociative('SELECT hash, filename, is_executable FROM executable_file WHERE immutable_execid = :id', ['id' => $immutableExecutable['immutable_execid']]);
uasort($files, fn(array $a, array $b) => strcmp($a['filename'], $b['filename']));
$newHash = md5(
join(
array_map(
fn(array $file) => $file['hash'] . $file['filename'] . (bool)$file['is_executable'],
$files
)
)
);
$this->connection->executeQuery('UPDATE immutable_executable SET hash = :hash WHERE immutable_execid = :id', [
'hash' => $newHash,
'id' => $immutableExecutable['immutable_execid'],
]);
}
$this->addSql('-- no-op'); // suppress warning "Migration <name> was executed but did not result in any SQL statements."
}

public function down(Schema $schema): void
{
// We don't handle this case
}

public function isTransactional(): bool
{
return false;
$this->addSql('-- no-op');
}
}
41 changes: 41 additions & 0 deletions webapp/migrations/Version20230508170000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20230508170000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Compute hashes of executable files';
// This migration is only required for databases that were migrated
// from DOMjudge 7.x using certain DOMjudge versions in the range 8.0.0
// to 8.3.0. Databases migrated from 7.x straight to 8.3.1+ will have
// the hashes computed by Version20201219154651.php.
}

public function up(Schema $schema): void
{
$executableFiles = $this->connection->fetchAllAssociative('SELECT execfileid, file_content FROM executable_file WHERE hash IS NULL');
foreach ($executableFiles as $file) {
$this->addSql('UPDATE executable_file SET hash = :hash WHERE execfileid = :id', [
'hash' => md5($file['file_content']),
'id' => $file['execfileid']
]);
}
}

public function down(Schema $schema): void
{
// We don't handle this case
}

public function isTransactional(): bool
{
return false;
}
}
50 changes: 50 additions & 0 deletions webapp/migrations/Version20230508180000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230508180000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Update hashes of immutable executables';
}

public function up(Schema $schema): void
{
$immutableExecutables = $this->connection->fetchAllAssociative('SELECT immutable_execid FROM immutable_executable');
foreach ($immutableExecutables as $immutableExecutable) {
$files = $this->connection->fetchAllAssociative('SELECT hash, filename, is_executable FROM executable_file WHERE immutable_execid = :id', ['id' => $immutableExecutable['immutable_execid']]);
uasort($files, fn(array $a, array $b) => strcmp($a['filename'], $b['filename']));
$newHash = md5(
join(
array_map(
fn(array $file) => $file['hash'] . $file['filename'] . (bool)$file['is_executable'],
$files
)
)
);
$this->addSql('UPDATE immutable_executable SET hash = :hash WHERE immutable_execid = :id', [
'hash' => $newHash,
'id' => $immutableExecutable['immutable_execid'],
]);
}
}

public function down(Schema $schema): void
{
// We don't handle this case
}

public function isTransactional(): bool
{
return false;
}
}
2 changes: 1 addition & 1 deletion webapp/migrations/Version20231120225210.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function up(Schema $schema): void

if ($updated) {
$newExtensionsJson = json_encode($extensions);
$this->connection->executeQuery('UPDATE language SET extensions = :extensions WHERE langid = :langid', [
$this->addSql('UPDATE language SET extensions = :extensions WHERE langid = :langid', [
'extensions' => $newExtensionsJson,
'langid' => $language['langid'],
]);
Expand Down
28 changes: 20 additions & 8 deletions webapp/migrations/Version20240511091916.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,33 @@ public function getDescription(): string

public function up(Schema $schema): void
{
foreach (self::COMPILER_VERSION_COMMAND as $lang => $versionCommand) {
$this->addSql("UPDATE language SET compiler_version_command = '" . $versionCommand ."' WHERE langid='" . $lang . "' AND compiler_version_command IS NULL;");
foreach (self::COMPILER_VERSION_COMMAND as $langid => $versionCommand) {
$this->addSql(
"UPDATE language SET compiler_version_command = :compiler_version_command WHERE langid = :langid AND compiler_version_command IS NULL",
['compiler_version_command' => $versionCommand, 'langid' => $langid]
);
}
foreach (self::RUNNER_VERSION_COMMAND as $lang => $versionCommand) {
$this->addSql("UPDATE language SET runner_version_command = '" . $versionCommand ."' WHERE langid='" . $lang . "' AND runner_version_command IS NULL;");
foreach (self::RUNNER_VERSION_COMMAND as $langid => $versionCommand) {
$this->addSql(
"UPDATE language SET runner_version_command = :compiler_version_command WHERE langid = :langid AND runner_version_command IS NULL",
['compiler_version_command' => $versionCommand, 'langid' => $langid]
);
}
}

public function down(Schema $schema): void
{
foreach (self::COMPILER_VERSION_COMMAND as $lang => $versionCommand) {
$this->addSql("UPDATE language SET compiler_version_command = NULL WHERE langid='" . $lang . "' AND compiler_version_command = '" . $versionCommand ."';");
foreach (self::COMPILER_VERSION_COMMAND as $langid => $versionCommand) {
$this->addSql(
"UPDATE language SET compiler_version_command = NULL WHERE langid = :langid AND compiler_version_command = :compiler_version_command",
['compiler_version_command' => $versionCommand, 'langid' => $langid]
);
}
foreach (self::RUNNER_VERSION_COMMAND as $lang => $versionCommand) {
$this->addSql("UPDATE language SET runner_version_command = NULL WHERE langid='" . $lang . "' AND runner_version_command = '" . $versionCommand ."';");
foreach (self::RUNNER_VERSION_COMMAND as $langid => $versionCommand) {
$this->addSql(
"UPDATE language SET runner_version_command = NULL WHERE langid = :langid AND runner_version_command = :compiler_version_command",
['compiler_version_command' => $versionCommand, 'langid' => $langid]
);
}
}

Expand Down
Loading