Skip to content
Draft
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
63 changes: 59 additions & 4 deletions WordPress/Tests/DB/PreparedSQLUnitTest.1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ $wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . esc_sql( $f
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . ABSINT( $foo ) . ";" ); // Ok.

// Test multi-line strings.
$all_post_meta = $wpdb->get_results( $wpdb->prepare( sprintf(
$all_post_meta = $wpdb->get_results( $wpdb->prepare( \SPRINTF(
'SELECT `post_id`, `meta_value`
FROM `%s`
WHERE `meta_key` = "sort_order"
Expand All @@ -45,7 +45,7 @@ $all_post_meta = $wpdb->get_results( $wpdb->prepare( sprintf(
$wpdb->query( "
SELECT *
FROM $wpdb->posts
WHERE post_title LIKE '" . esc_sql( $foo ) . "';"
WHERE post_title LIKE '" . \esc_SQL( $foo ) . "';"
); // Ok.

$wpdb->query( $wpdb->prepare( "
Expand Down Expand Up @@ -143,5 +143,60 @@ echo $wpdb::CONSTANT_NAME;
// Not an identifiable method call.
$wpdb->{$methodName}('query');

// Don't throw an error during live coding.
wpdb::prepare( "SELECT * FROM $wpdb->posts
/*
* Safeguard correct handling of all types of namespaced calls to the WPDB::prepare() method.
*
* Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the
* sniff handles those calls.
*
* Except for the fully qualified global call, the calls below are currently false positives. The sniff
* incorrectly identifies calls to a non-global class named `wpdb` preceded by a namespace separator as calls to the
* global `$wpdb` object. Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710.
*/
\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" );
MyNamespace\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" );
\MyNamespace\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" );
namespace\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // False positive (see comment above). This should be flagged in the future once the sniff is able to resolve relative namespaces.
namespace\Sub\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" );

/*
* Safeguard correct handling of all types of namespaced calls to PreparedSQLSniff::$SQLEscapingFunctions.
*
* Note: The sniff currently has a limitation in how it identifies and counts errors for namespaced function calls that
* match function names in $SQLEscapingFunctions, $SQLAutoEscapedFunctions, or
* FormattingFunctionsHelper::$formattingFunctions. When it encounters such a call, it treats the function name as if it
* were a global function call and skips checking the contents. For example, `MyNamespace\absint( $foo )` should trigger
* two errors (one for MyNamespace\absint, one for $foo), but currently only triggers one error for "MyNamespace"
* because the sniff incorrectly treats "absint" as a valid global escaping function and skips its contents.
* Additionally, multi-level namespace calls like `namespace\Sub\count( $foo )` generate multiple errors (one for
* "namespace", one for "Sub") instead of recognizing it as a single namespaced function call. This will be easier to
* fix once only PHPCS 4 is supported. Reported in https://github.com/WordPress/WordPress-Coding-Standards/issues/2648.
*/
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . \absint( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . MyNamespace\esc_sql( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . \MyNamespace\intval( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . namespace\floatval( $foo ) ); // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . namespace\Sub\like_escape( $foo ) );

/*
* Safeguard correct handling of all types of namespaced calls to PreparedSQLSniff::$SQLAutoEscapedFunctions.
*
* Note: See the comment above the $SQLEscapingFunctions tests for details about the sniff's current limitations.
*/
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . \count( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . \Count( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . MyNamespace\count( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . \MyNamespace\count( $foo ) );
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . namespace\count( $foo ) ); // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . namespace\Sub\count( $foo ) );

/*
* Safeguard correct handling of all types of namespaced calls to FormattingFunctionsHelper::$formattingFunctions.
*
* Note: See the comment above the $SQLEscapingFunctions tests for details about the sniff's current limitations.
*/
$wpdb->get_results( \sprintf( "SELECT * FROM $wpdb->posts WHERE ID = %s", intval( $id ) ) );
$wpdb->get_results( MyNamespace\wp_sprintf( "SELECT * FROM $wpdb->posts WHERE ID = %s", intval( $id ) ) );
$wpdb->get_results( \MyNamespace\sprintf( "SELECT * FROM $wpdb->posts WHERE ID = %s", intval( $id ) ) );
$wpdb->get_results( namespace\wp_sprintf( "SELECT * FROM $wpdb->posts WHERE ID = %s", intval( $id ) ) ); // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
$wpdb->get_results( namespace\Sub\sprintf( "SELECT * FROM $wpdb->posts WHERE ID = %s", intval( $id ) ) );
8 changes: 8 additions & 0 deletions WordPress/Tests/DB/PreparedSQLUnitTest.3.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

/*
* Intentional parse error (unclosed string).
* This should be the only test in this file.
*/

wpdb::prepare( "SELECT * FROM $wpdb->posts
23 changes: 23 additions & 0 deletions WordPress/Tests/DB/PreparedSQLUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ public function getErrorList( $testFile = '' ) {
124 => 1,
128 => 1,
132 => 2,
156 => 1,

/**
* False positives. See https://github.com/WordPress/WordPress-Coding-Standards/issues/2710 and
* comment in the test case file.
*/
157 => 1,
158 => 1,
159 => 1,
160 => 1,

176 => 1,
177 => 1,
178 => 1,
179 => 2,
188 => 1,
189 => 1,
190 => 1,
191 => 2,
199 => 1,
200 => 1,
201 => 1,
202 => 2,
);

case 'PreparedSQLUnitTest.2.inc':
Expand Down
Loading