Bug cerber user role editor

Hello Cerber Team,

Bug Report: Issue with crb_array_diff_keys in WP Cerber and User Role Editor

Error Encountered:

Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, bool given in /wp-content/plugins/wp-cerber/cerber-common.php on line 1124


#### Environment:

* **WordPress Version:** 6.7.1
* **WP Cerber Version:** 9.6.5
* **User Role Editor Version:** 4.64.4
* **PHP Version:** 8.1

#### Details:

The error seems to originate from the `crb_array_diff_keys` function in the file `/wp-content/plugins/wp-cerber/cerber-common.php` . Here is the original code:

/**

  • Compare two arrays by using keys: check if two arrays have a different set of keys

  • @param $arr1 array

  • @param $arr2 array

  • @return bool true if arrays have different set of keys
    */
    function crb_array_diff_keys( &$arr1, &$arr2 ) {
    if ( count( $arr1 ) != count( $arr2 ) ) {
    return true;
    }
    if ( array_diff_key( $arr1, $arr2 ) ) {
    return true;
    }
    if ( array_diff_key( $arr2, $arr1 ) ) {
    return true;
    }

    return false;
    }


The issue occurs when the function receives a variable `$arr1` or `$arr2` that is neither an array nor an instance of `Countable` . In such cases, the call to `count()` triggers a fatal error.

#### Suggested Fix:

To resolve this issue, I modified the `crb_array_diff_keys` function to include validation of the arguments before using `count()` . Here is the updated function:

/**

  • Compare two arrays by using keys: check if two arrays have a different set of keys

  • @param mixed $arr1 Array or Countable

  • @param mixed $arr2 Array or Countable

  • @return bool True if arrays have a different set of keys
    */
    function crb_array_diff_keys( &$arr1, &$arr2 ) {
    if ( !is_array( $arr1 ) || !is_array( $arr2 ) ) {
    return true; // Return true if either parameter is not an array
    }

    if ( count( $arr1 ) != count( $arr2 ) ) {
    return true;
    }

    if ( array_diff_key( $arr1, $arr2 ) ) {
    return true;
    }

    if ( array_diff_key( $arr2, $arr1 ) ) {
    return true;
    }

    return false;
    }


#### Result:

* This change ensures the function does not attempt to count a variable that is not an array or an instance of `Countable` .
* It prevents the fatal error while maintaining the intended functionality.

#### Feedback and Inquiry:

While this fix works for my environment, I’m unsure if it is universally applicable to other parts of WP Cerber’s codebase. I’m submitting this bug report and solution here in case it is helpful for future updates or for others encountering a similar issue.

If you need further details or testing, I’m happy to assist.

Thank you for your time and support!

Best regards,

Ovnis 🛸😊
1 Like

Thanks for reporting the bug. We will fix in the upcoming version.

Fixed in WP Cerber 9.6.6. We’ve implemented logging of software errors to a designated log, which can be viewed on the Diagnostics page.

Thank you for your quick response and for fixing the issue in 9.6.6 The new logging system on the Diagnostics page is a great addition.

I have identified a few additional points in cerber-common.php, notably a deprecation error in PHP 8.2 (line 3767) bug admin where preg_replace() attempts to process a NULL value , which is no longer allowed. The root cause of this issue is difficult to pinpoint, as it could be related to a database retrieval issue, an uninitialized user input, or an improperly defined variable.

Additionally, after further analysis, the crb_sanitize_id() and crb_sanitize_alphanum() functions could be optimized for better compatibility with PHP 8.2. In particular, crb_sanitize_id() could benefit from stricter type validation and length constraints, while crb_sanitize_alphanum() could improve UTF-8 encoding handling to prevent character loss.

code crb_sanitize_id

1296 function crb_sanitize_id( $id = ‘’ ) {
1297 if ( ! $id ) {
1298 return ‘’;
1299 }
1300
1301 return substr( preg_replace( CRB_SANITIZE_ID, ‘_’, (string) $id ), 0, 64 );
1302 }

by

1296 function crb_sanitize_id( $id = ‘’ ) {
1297 // VĂŠrifie si $id est null ou une chaĂŽne vide
1298 if ( is_null( $id ) || $id === ‘’ ) {
1299 return ‘’;
1300 }
1301
1302 // VÊrifie si $id est bien une chaÎne de caractères avant de le traiter
1303 $id = (string) $id;
1304
1305 // Sécurise l’ID en remplaçant les caractères interdits par ""
1306 $id = preg_replace( CRB_SANITIZE_ID, '
', $id ) ?? ‘’;
1307
1308 // Retourne une version limitÊe à 64 caractères
1309 return substr( $id, 0, 64 );
1310 }

sorry // im french :slightly_smiling_face:‍:arrow_up_down::grin:

code crb_sanitize_alphanum

1316 function crb_sanitize_alphanum( $value, $check_utf8 = false ) {
1317
1318 if ( is_array( $value ) ) {
1319 return array_map( function ( $val ) use ( $check_utf8 ) {
1320 return crb_sanitize_alphanum( $val, $check_utf8 );
1321 }, $value );
1322 }
1323
1324 if ( $check_utf8
1325 && ! preg_match(‘/[1]*$/’, $value) ) {
1326 $value = iconv( ‘UTF-8’, ‘UTF-8//IGNORE’, $value ); // Delete invalid UTF-8
1327 }
1328
1329 return preg_replace( ‘/\W/’, ‘’, $value );
1330 }

by

1316 function crb_sanitize_alphanum( $value, $check_utf8 = false ) {
1317
1318 if ( is_array( $value ) ) {
1319 return array_map( function ( $val ) use ( $check_utf8 ) {
1320 return crb_sanitize_alphanum( $val, $check_utf8 );
1321 }, $value );
1322 }
1323
1324 // Vérifie si la valeur est bien une chaîne avant de l’utiliser
1325 if ( ! is_string( $value ) ) {
1326 return ‘’;
1327 }
1328
1329 if ( $check_utf8 && ! preg_match(‘/[2]*$/’, $value) ) {
1330 $value = iconv( ‘UTF-8’, ‘UTF-8//IGNORE’, $value ); // Supprime les caractères UTF-8 invalides
1331 }
1332
1333 return preg_replace( ‘/\W/’, ‘’, $value ) ?? ‘’;
1334 }

Here is a simple code enhancement proposal. It is clear that with the thousands of lines of code you have to manage, some issues can become hard to spot.

I am still investigating the deprecation warning on line 3767, which appears to be a **deeper underlying issue php 8.2


  1. \x00-\x7F ↩︎

  2. \x00-\x7F ↩︎

PHP 8.2 – Up to version 8.2.27, no errors were encountered. The issue appears to start between PHP 8.2.27 and PHP 8.2.29. It may be related to recent modifications in preg_replace(). Needs verification. cerber common