Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Utils\TextStrings;
use WordPressCS\WordPress\Helpers\ConstantsHelper;
use WordPressCS\WordPress\Helpers\ContextHelper;
use WordPressVIPMinimum\Sniffs\Sniff;

/**
Expand All @@ -37,6 +39,24 @@ class RestrictedConstantsSniff extends Sniff {
'WP_CRON_CONTROL_SECRET',
];

/**
* List of constants which do not hold a reliable value on the VIP Platform.
*
* @var array<string, string> Key is the constant name, value is the error message to use.
*/
private $unreliableConstants = [
'DB_NAME' => 'The `%s` constant is set to null on the VIP Platform and does not hold the actual database name.',
];

/**
* Functions which resolve a constant based on a constant name passed as a text string.
*
* @var array<string, bool> Key is the function name in lowercase, value is irrelevant.
*/
private $constantNameFunctions = [
'constant' => true,
];

/**
* List of (global) constant names, which should not be referenced in userland code, nor (re-)declared.
*
Expand Down Expand Up @@ -91,6 +111,11 @@ public function process_token( $stackPtr ) {
$constantName = TextStrings::stripQuotes( $this->tokens[ $stackPtr ]['content'] );
}

if ( isset( $this->unreliableConstants[ $constantName ] ) === true ) {
$this->process_unreliable_constant( $stackPtr, $constantName );
return;
}

if ( isset( $this->restrictedConstants[ $constantName ] ) === false
&& isset( $this->restrictedRedeclaration[ $constantName ] ) === false
) {
Expand Down Expand Up @@ -138,4 +163,32 @@ public function process_token( $stackPtr ) {
}
}
}

/**
* Process a token containing the name of a constant which does not hold a reliable value
* on the VIP Platform.
*
* @param int $stackPtr The position of the current token in the stack passed in $tokens.
* @param string $constantName The name of the constant.
*
* @return void
*/
private function process_unreliable_constant( $stackPtr, $constantName ) {
if ( $this->tokens[ $stackPtr ]['code'] === T_STRING ) {
if ( ConstantsHelper::is_use_of_global_constant( $this->phpcsFile, $stackPtr ) === false ) {
// Class constant, property, function name or something else which just shares the name.
return;
}
} elseif ( ContextHelper::is_in_function_call( $this->phpcsFile, $stackPtr, $this->constantNameFunctions ) === false ) {
// A text string only refers to the constant when passed to constant().
return;
}

$this->phpcsFile->addError(
$this->unreliableConstants[ $constantName ],
$stackPtr,
'UnreliableConstant',
[ $constantName ]
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ public function getGroups() {
'$wpdb->users',
],
],
'db_name' => [
'type' => 'error',
'message' => 'The `$wpdb->dbname` property is set to null on the VIP Platform and does not hold the actual database name.',
'object_vars' => [
'$wpdb->dbname',
],
],
'session' => [
'type' => 'error',
'message' => 'Usage of $_SESSION variable is prohibited.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,29 @@ if ( constant( 'WP_CRON_CONTROL_SECRET' ) ) { // Okay. Can touch.
}

define( '"A8C_PROXIED_REQUEST"', false ); // Okay, well not really as the name is not a valid PHP constant name, but that's not our concern.

$name = DB_NAME; // Bad. The constant is null on the platform.

$name = constant( 'DB_NAME' ); // Bad. The constant is null on the platform.

if ( defined( 'DB_NAME' ) ) { // Okay. Checking whether a constant exists is not the same as using it.

}

$name = My_Class::DB_NAME; // Okay. Class constant.

$name = $wpdb->DB_NAME; // Okay. Object property.

$name = DB_NAME(); // Okay. Function call.

$name = my_function( 'DB_NAME' ); // Okay. Just a text string.

$name = [ 'DB_NAME' => 'my_database' ]; // Okay. Just a text string.

class My_Class {
const DB_NAME = 'my_database'; // Okay. Class constant declaration.
}

$name = \DB_NAME; // Bad. Fully qualified reference to the global constant.

$name = My_Namespace\DB_NAME; // Okay. Namespaced constant which just shares the name.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public function getErrorList() {
11 => 1,
13 => 1,
15 => 1,
27 => 1,
29 => 1,
49 => 1,
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ $query = "SELECT * FROM $wpdb->users"; // Error.

$wp_db->update( $wpdb->users, array( 'displayname' => 'Kanobe!' ), array( 'ID' => 1 ) ); // Error.




$db_name = $wpdb->dbname; // Error.
$query = "SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$wpdb->dbname'"; // Error.
$db_name = $other_db->dbname; // Ok, not $wpdb.

$query = "SELECT * FROM $wpdb->posts"; // Ok.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public function getErrorList() {
return [
3 => 1,
5 => 1,
7 => 1,
8 => 1,
23 => 1,
36 => 1,
37 => 1,
Expand Down