diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 7a6cf01..a440d78 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -3151,7 +3151,8 @@ public function testTranslateLikeBinary() { // Test escaping - "\\\%" is "\" and a wildcard $result = $this->assertQuery( "SELECT * FROM _tmp_table WHERE name LIKE BINARY 'special\\\\\\%chars'" ); - $this->assertCount( 0, $result ); + $this->assertCount( 1, $result ); + $this->assertEquals( 'special\\chars', $result[0]->name ); // Test LIKE without BINARY $result = $this->assertQuery( "SELECT * FROM _tmp_table WHERE name LIKE 'FIRST'" ); diff --git a/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php b/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php index bcb971a..2dc265a 100644 --- a/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php +++ b/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php @@ -794,41 +794,17 @@ public function _helper_like_to_glob_pattern( $pattern ) { $pattern = str_replace( '*', '[*]', $pattern ); $pattern = str_replace( '?', '[?]', $pattern ); - $glob_pattern = ''; - for ( $i = 0; $i < strlen( $pattern ); $i += 1 ) { - $byte1 = $pattern[ $i ]; - if ( '\\' === $byte1 ) { - // Add the escape character. - $glob_pattern .= $byte1; - - // Special case: "\\%" and "\\_" are equivalent to "\%" and "\_". - // In such case, we need to skip the extra backslash. - $byte2 = $pattern[ $i + 1 ] ?? null; - $byte3 = $pattern[ $i + 2 ] ?? null; - if ( '\\' === $byte2 && ( '%' === $byte3 || '_' === $byte3 ) ) { - $glob_pattern .= $byte3; - $i += 2; - continue; - } - - // We're in an escape sequence. Add the next character as it is. - $glob_pattern .= $byte2; - $i += 1; - } elseif ( '%' === $byte1 ) { - $glob_pattern .= '*'; - } elseif ( '_' === $byte1 ) { - $glob_pattern .= '?'; - } else { - $glob_pattern .= $byte1; - } - } + $pattern = preg_replace('/(^|[^\\\\](?:\\\\{2}))*(\\\\[%_])/', '$1\\\\$2', $pattern); // 1. Unescape C-style escape sequences. - $glob_pattern = stripcslashes($glob_pattern); + $pattern = stripcslashes($pattern); - // 2. Unescape LIKE escape sequences. - $glob_pattern = preg_replace('/\\\\(.)/', '$1', $glob_pattern); + $pattern = preg_replace('/(^|[^\\\\](?:\\\\{2})*)%/', '$1*', $pattern); + $pattern = preg_replace('/(^|[^\\\\](?:\\\\{2})*)_/', '$1?', $pattern); - return $glob_pattern; + // 2. Unescape LIKE escape sequences. + $pattern = preg_replace('/\\\\(.)/', '$1', $pattern); + + return $pattern; } }