Merge pull request #15168 from uberbrady/improve_restore_sanitization

Improve restore sanitization - Fixes [sc-24840]
This commit is contained in:
snipe 2024-07-25 18:20:05 +01:00 committed by GitHub
commit 129d3b35fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -30,8 +30,11 @@ class SQLStreamer {
public function parse_sql(string $line): string { public function parse_sql(string $line): string {
// take into account the 'start of line or not' setting as an instance variable? // take into account the 'start of line or not' setting as an instance variable?
// 'continuation' lines for a permitted statement are PERMITTED. // 'continuation' lines for a permitted statement are PERMITTED.
// remove *only* line-feeds & carriage-returns; helpful for regexes against lines from
// Windows dumps
$line = trim($line, "\r\n");
if($this->statement_is_permitted && $line[0] === ' ') { if($this->statement_is_permitted && $line[0] === ' ') {
return $line; return $line . "\n"; //re-add the newline
} }
$table_regex = '`?([a-zA-Z0-9_]+)`?'; $table_regex = '`?([a-zA-Z0-9_]+)`?';
@ -42,8 +45,12 @@ class SQLStreamer {
"/^(INSERT INTO )$table_regex(.*)$/" => false, "/^(INSERT INTO )$table_regex(.*)$/" => false,
"/^UNLOCK TABLES/" => false, "/^UNLOCK TABLES/" => false,
// "/^\\) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;/" => false, // FIXME not sure what to do here? // "/^\\) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;/" => false, // FIXME not sure what to do here?
"/^\\)[a-zA-Z0-9_= ]*;$/" => false "/^\\)[a-zA-Z0-9_= ]*;$/" => false,
// ^^^^^^ that bit should *exit* the 'perimitted' black // ^^^^^^ that bit should *exit* the 'permitted' block
"/^\\(.*\\)[,;]$/" => false, //older MySQL dump style with one set of values per line
/* we *could* have made the ^INSERT INTO blah VALUES$ turn on the capturing state, and closed it with
a ^(blahblah);$ but it's cleaner to not have to manage the state machine. We're just going to
assume that (blahblah), or (blahblah); are values for INSERT and are always acceptable. */
]; ];
foreach($allowed_statements as $statement => $statechange) { foreach($allowed_statements as $statement => $statechange) {
@ -67,7 +74,7 @@ class SQLStreamer {
} }
//how do we *replace* the tablename? //how do we *replace* the tablename?
// print "RETURNING LINE: $line"; // print "RETURNING LINE: $line";
return $line; return $line . "\n"; //re-add newline
} }
} }
// all that is not allowed is denied. // all that is not allowed is denied.
@ -164,7 +171,8 @@ class RestoreFromBackup extends Command
{filename : The zip file to be migrated} {filename : The zip file to be migrated}
{--no-progress : Don\'t show a progress bar} {--no-progress : Don\'t show a progress bar}
{--sanitize-guess-prefix : Guess and output the table-prefix needed to "sanitize" the SQL} {--sanitize-guess-prefix : Guess and output the table-prefix needed to "sanitize" the SQL}
{--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}'; {--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}
{--sql-stdout-only : ONLY "Sanitize" the SQL and print it to stdout - useful for debugging - probably requires --sanitize-with-prefix= }';
/** /**
* The console command description. * The console command description.
@ -365,6 +373,15 @@ class RestoreFromBackup extends Command
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL."); return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL.");
} }
// If we're doing --sql-stdout-only, handle that now so we don't have to open pipes to mysql and all of that silliness
if ($this->option('sql-stdout-only')) {
$sql_importer = new SQLStreamer($sql_contents, STDOUT, $this->option('sanitize-with-prefix'));
$bytes_read = $sql_importer->line_aware_piping();
return $this->warn("$bytes_read total bytes read");
//TODO - it'd be nice to dump this message to STDERR so that STDOUT is just pure SQL,
// which would be good for redirecting to a file, and not having to trim the last line off of it
}
//how to invoke the restore? //how to invoke the restore?
$pipes = []; $pipes = [];