Skip to content

Commit a1e19e9

Browse files
authored
Merge pull request #115 from wp-cli/verify-and-whitelist-sql-escaping
Verify and whitelist SQL escaping
2 parents 7bfa0b7 + bea87da commit a1e19e9

File tree

1 file changed

+28
-4
lines changed

1 file changed

+28
-4
lines changed

src/Search_Replace_Command.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,10 @@ public function __invoke( $args, $assoc_args ) {
321321

322322
if ( $this->export_handle ) {
323323
fwrite( $this->export_handle, "\nDROP TABLE IF EXISTS $table_sql;\n" );
324+
325+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
324326
$row = $wpdb->get_row( "SHOW CREATE TABLE $table_sql", ARRAY_N );
327+
325328
fwrite( $this->export_handle, $row[1] . ";\n" );
326329
list( $table_report, $total_rows ) = $this->php_export_table( $table, $old, $new );
327330
if ( $this->report ) {
@@ -367,7 +370,10 @@ public function __invoke( $args, $assoc_args ) {
367370
if ( ! $php_only && ! $this->regex ) {
368371
$col_sql = self::esc_sql_ident( $col );
369372
$wpdb->last_error = '';
370-
$serial_row = $wpdb->get_row( "SELECT * FROM $table_sql WHERE $col_sql REGEXP '^[aiO]:[1-9]' LIMIT 1" );
373+
374+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
375+
$serial_row = $wpdb->get_row( "SELECT * FROM $table_sql WHERE $col_sql REGEXP '^[aiO]:[1-9]' LIMIT 1" );
376+
371377
// When the regex triggers an error, we should fall back to PHP
372378
if ( false !== strpos( $wpdb->last_error, 'ERROR 1139' ) ) {
373379
$serial_row = true;
@@ -492,12 +498,14 @@ private function sql_handle_col( $col, $primary_keys, $table, $old, $new ) {
492498
if ( $this->log_handle ) {
493499
$count = $this->log_sql_diff( $col, $primary_keys, $table, $old, $new );
494500
} else {
501+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
495502
$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT($col_sql) FROM $table_sql WHERE $col_sql LIKE BINARY %s;", '%' . self::esc_like( $old ) . '%' ) );
496503
}
497504
} else {
498505
if ( $this->log_handle ) {
499506
$this->log_sql_diff( $col, $primary_keys, $table, $old, $new );
500507
}
508+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
501509
$count = $wpdb->query( $wpdb->prepare( "UPDATE $table_sql SET $col_sql = REPLACE($col_sql, %s, %s);", $old, $new ) );
502510
}
503511

@@ -518,7 +526,10 @@ private function php_handle_col( $col, $primary_keys, $table, $old, $new ) {
518526
$col_sql = self::esc_sql_ident( $col );
519527
$where = $this->regex ? '' : " WHERE $col_sql" . $wpdb->prepare( ' LIKE BINARY %s', '%' . self::esc_like( $old ) . '%' );
520528
$primary_keys_sql = implode( ',', self::esc_sql_ident( $primary_keys ) );
521-
$rows = $wpdb->get_results( "SELECT {$primary_keys_sql} FROM {$table_sql} {$where}" );
529+
530+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
531+
$rows = $wpdb->get_results( "SELECT {$primary_keys_sql} FROM {$table_sql} {$where}" );
532+
522533
foreach ( $rows as $keys ) {
523534
$where_sql = '';
524535
foreach ( (array) $keys as $k => $v ) {
@@ -527,7 +538,10 @@ private function php_handle_col( $col, $primary_keys, $table, $old, $new ) {
527538
}
528539
$where_sql .= self::esc_sql_ident( $k ) . ' = ' . self::esc_sql_value( $v );
529540
}
541+
542+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
530543
$col_value = $wpdb->get_var( "SELECT {$col_sql} FROM {$table_sql} WHERE {$where_sql}" );
544+
531545
if ( '' === $col_value ) {
532546
continue;
533547
}
@@ -609,9 +623,11 @@ private function write_sql_row_fields( $table, $rows ) {
609623

610624
if ( method_exists( $wpdb, 'remove_placeholder_escape' ) ) {
611625
// since 4.8.3
626+
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- verified inputs above
612627
$sql = $wpdb->remove_placeholder_escape( $wpdb->prepare( $sql, array_values( $values ) ) );
613628
} else {
614629
// 4.8.2 or less
630+
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- verified inputs above
615631
$sql = $wpdb->prepare( $sql, array_values( $values ) );
616632
}
617633

@@ -638,7 +654,10 @@ private static function get_columns( $table ) {
638654
$text_columns = array();
639655
$all_columns = array();
640656
$suppress_errors = $wpdb->suppress_errors();
641-
$results = $wpdb->get_results( "DESCRIBE $table_sql" );
657+
658+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
659+
$results = $wpdb->get_results( "DESCRIBE $table_sql" );
660+
642661
if ( ! empty( $results ) ) {
643662
foreach ( $results as $col ) {
644663
if ( 'PRI' === $col->Key ) {
@@ -775,7 +794,12 @@ private function log_sql_diff( $col, $primary_keys, $table, $old, $new ) {
775794
$primary_keys_sql = '';
776795
}
777796

778-
$results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_keys_sql}`$col` FROM `$table` WHERE `$col` LIKE BINARY %s", '%' . self::esc_like( $old ) . '%' ), ARRAY_N );
797+
$table_sql = self::esc_sql_ident( $table );
798+
$col_sql = self::esc_sql_ident( $col );
799+
800+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
801+
$results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_keys_sql}{$col_sql} FROM {$table_sql} WHERE {$col_sql} LIKE BINARY %s", '%' . self::esc_like( $old ) . '%' ), ARRAY_N );
802+
779803
if ( empty( $results ) ) {
780804
return 0;
781805
}

0 commit comments

Comments
 (0)