Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Code Obfuscation Check to display multiple errors #366

Closed
wants to merge 3 commits into from
Closed
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
46 changes: 46 additions & 0 deletions includes/Checker/Checks/Abstract_File_Check.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@
return false;
}

/**
* Returns matched files performing a regular expression match on the file contents of the given list of files.
*
* @since n.e.x.t
*
* @param string $pattern The pattern to search for.
* @param array $files List of absolute file paths.
* @return array|bool Array of file paths and matched string/pattern if matches were found, false otherwise.
*/
final protected static function files_preg_match( $pattern, array $files ) {
$matched_files = array();

foreach ( $files as $file ) {
$matches = array();

$matched_file_name = self::file_preg_match( $pattern, array( $file ), $matches );

if ( false !== $matched_file_name ) {
$matched_files[] = array( $matched_file_name, $matches[0] );

Check warning on line 162 in includes/Checker/Checks/Abstract_File_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Abstract_File_Check.php#L162

Added line #L162 was not covered by tests
}
}
return count( $matched_files ) > 0 ? $matched_files : false;
}

/**
* Performs a check indicating if the needle is contained in the file contents of the given list of files.
*
Expand All @@ -163,6 +187,28 @@
return false;
}

/**
* Returns matched files performing a check indicating if the needle is contained in the file contents of the given list of files.
*
* @since n.e.x.t
*
* @param array $files List of absolute file paths.
* @param string $needle The substring to search for.
* @return array|bool Array of file path and matched string if needle was found, false otherwise.
*/
final protected static function files_str_contains( array $files, $needle ) {
$matched_files = array();

foreach ( $files as $file ) {
$matched_file_name = self::file_str_contains( array( $file ), $needle );

if ( false !== $matched_file_name ) {
$matched_files[] = array( $matched_file_name, $needle );

Check warning on line 206 in includes/Checker/Checks/Abstract_File_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Abstract_File_Check.php#L206

Added line #L206 was not covered by tests
}
}
return count( $matched_files ) > 0 ? $matched_files : false;
}

/**
* Gets the contents of the given file.
*
Expand Down
78 changes: 42 additions & 36 deletions includes/Checker/Checks/Code_Obfuscation_Check.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,20 @@
* @param array $php_files List of absolute PHP file paths.
*/
protected function look_for_zendguard( Check_Result $result, array $php_files ) {
$obfuscated_file = self::file_preg_match( '/(<\?php \@Zend;)|(This file was encoded by)/', $php_files );
if ( $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'Zend Guard', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file
);
$obfuscated_files = self::files_preg_match( '/(<\?php \@Zend;)|(This file was encoded by)/', $php_files );
if ( $obfuscated_files ) {
foreach ( $obfuscated_files as $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(

Check warning on line 102 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L99-L102

Added lines #L99 - L102 were not covered by tests
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'Zend Guard', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file[0]

Check warning on line 108 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L104-L108

Added lines #L104 - L108 were not covered by tests
);
}
}
}

Expand All @@ -118,18 +120,20 @@
* @param array $php_files List of absolute PHP file paths.
*/
protected function look_for_sourceguardian( Check_Result $result, array $php_files ) {
$obfuscated_file = self::file_preg_match( "/(sourceguardian\.com)|(function_exists\('sg_load'\))|(\$__x=)/", $php_files );
if ( $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'Source Guardian', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file
);
$obfuscated_files = self::files_preg_match( "/(sourceguardian\.com)|(function_exists\('sg_load'\))|(\$__x=)/", $php_files );
if ( $obfuscated_files ) {
foreach ( $obfuscated_files as $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(

Check warning on line 128 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L125-L128

Added lines #L125 - L128 were not covered by tests
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'Source Guardian', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file[0]

Check warning on line 134 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L130-L134

Added lines #L130 - L134 were not covered by tests
);
}
}
}

Expand All @@ -142,18 +146,20 @@
* @param array $php_files List of absolute PHP file paths.
*/
protected function look_for_ioncube( Check_Result $result, array $php_files ) {
$obfuscated_file = self::file_str_contains( $php_files, 'ionCube' );
if ( $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'ionCube', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file
);
$obfuscated_files = self::files_str_contains( $php_files, 'ionCube' );
if ( $obfuscated_files ) {
foreach ( $obfuscated_files as $obfuscated_file ) {
$this->add_result_error_for_file(
$result,
sprintf(

Check warning on line 154 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L151-L154

Added lines #L151 - L154 were not covered by tests
/* translators: %s: tool name */
__( 'Code Obfuscation tools are not permitted. Detected: %s', 'plugin-check' ),
__( 'ionCube', 'plugin-check' )
),
'obfuscated_code_detected',
$obfuscated_file[0]

Check warning on line 160 in includes/Checker/Checks/Code_Obfuscation_Check.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Checks/Code_Obfuscation_Check.php#L156-L160

Added lines #L156 - L160 were not covered by tests
);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
/**
* Plugin Name: Test Plugin Code Obfuscation ionCube Multiple Errors
* Plugin URI: https://github.com/WordPress/plugin-check
* Description: Some plugin description.
* Author: WordPress Performance Team
* Author URI: https://make.wordpress.org/performance/
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* Text Domain: test-plugin-code-obfuscation-ioncube-multiple-errors
*
* @package test-plugin-code-obfuscation-ioncube-multiple-errors
*/

/**
* Just the word "ionCube" in this file will trigger the detection.
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php // Just the word "ionCube" in this file will trigger the detection.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
/**
* Plugin Name: Test Plugin Code Obfuscation Source Guardian Multiple Errors
* Plugin URI: https://github.com/WordPress/plugin-check
* Description: Some plugin description.
* Author: WordPress Performance Team
* Author URI: https://make.wordpress.org/performance/
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* Text Domain: test-plugin-code-obfuscation-sourceguardian-multiple-errors
*
* @package test-plugin-code-obfuscation-sourceguardian-multiple-errors
*/

/**
* Files contain code which is used to detect Source Guardian obfuscated files.
*/
require_once __DIR__ . '/obfuscated.php';
require_once __DIR__ . '/obfuscated2.php';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php
if(function_exists('sg_load')) {
$random_global = 'random_string';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?php
$domain = 'sourceguardian.com';
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* Plugin Name: Test Plugin Code Obfuscation Zend Guard Multiple Errors
* Plugin URI: https://github.com/WordPress/plugin-check
* Description: Some plugin description.
* Author: WordPress Performance Team
* Author URI: https://make.wordpress.org/performance/
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* Text Domain: test-plugin-code-obfuscation-zendguard-multiple-errors
*
* @package test-plugin-code-obfuscation-zendguard-multiple-errors
*/

// This constant is defined here to prevent fatal errors from the file below.
if ( ! defined( 'Zend' ) ) {
define( 'Zend', true );
}

/**
* Files contain code which is used to detect Zend Guard obfuscated files.
*/
require_once __DIR__ . '/obfuscated.php';
require_once __DIR__ . '/obfuscated2.php';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php @Zend;

$random_global = 'random_string';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?php
$message = 'This file was encoded by Zend';
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ public function test_run_with_obfuscation_errors( $type_flag, $plugin_basename,
$this->assertSame( 'obfuscated_code_detected', $errors[ $expected_file ][0][0][0]['code'] );
}

/**
* @dataProvider data_obfuscation_services_multiple_files
*/
public function test_run_with_obfuscation_multiple_errors( $type_flag, $plugin_basename, $expected_files ) {
$check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . $plugin_basename );
$check_result = new Check_Result( $check_context );

$check = new Code_Obfuscation_Check( $type_flag );
$check->run( $check_result );

$errors = $check_result->get_errors();

$this->assertNotEmpty( $errors );
$this->assertSame( sort( $expected_files ), sort( array_keys( $errors ) ) );
$this->assertSame( 2, $check_result->get_error_count() );

$this->assertTrue( isset( $errors[ $expected_files[0] ][0][0][0] ) );
$this->assertSame( 'obfuscated_code_detected', $errors[ $expected_files[0] ][0][0][0]['code'] );
$this->assertTrue( isset( $errors[ $expected_files[1] ][0][0][0] ) );
$this->assertSame( 'obfuscated_code_detected', $errors[ $expected_files[1] ][0][0][0]['code'] );
}

public function data_obfuscation_services() {
return array(
'Zend Guard' => array(
Expand All @@ -52,6 +74,26 @@ public function data_obfuscation_services() {
);
}

public function data_obfuscation_services_multiple_files() {
return array(
'Zend Guard Multiple' => array(
Code_Obfuscation_Check::TYPE_ZEND,
'test-plugin-code-obfuscation-zendguard-multiple-errors/load.php',
array( 'obfuscated.php', 'obfuscated2.php' ),
),
'Source Guardian Multiple' => array(
Code_Obfuscation_Check::TYPE_SOURCEGUARDIAN,
'test-plugin-code-obfuscation-sourceguardian-multiple-errors/load.php',
array( 'obfuscated.php', 'obfuscated2.php' ),
),
'ionCube Multiple' => array(
Code_Obfuscation_Check::TYPE_IONCUBE,
'test-plugin-code-obfuscation-ioncube-multiple-errors/load.php',
array( 'load.php', 'obfuscated.php' ),
),
);
}

public function test_run_without_any_obfuscation_errors() {
// Test plugin without any obfuscation.
$check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-i18n-usage-without-errors/load.php' );
Expand Down