Function Reference: benchmark_pcre_backtracking

Summary

Determine approximate backtrack count when running PCRE.

Return Values

(int)
  • The backtrack count.

Source Code

function benchmark_pcre_backtracking( $pattern, $subject, $strategy ) {
	$saved_config = ini_get( 'pcre.backtrack_limit' );
	
	// Attempt to prevent PHP crashes.  Adjust these lower when needed.
	if ( version_compare( phpversion(), '5.4.8', '>' ) ) {
		$limit = 1000000;
	} else {
		$limit = 20000;  // 20,000 is a reasonable upper limit, but see also https://core.trac.wordpress.org/ticket/29557#comment:10
	}

	// Start with small numbers, so if a crash is encountered at higher numbers we can still debug the problem.
	for( $i = 4; $i <= $limit; $i *= 2 ) {

		ini_set( 'pcre.backtrack_limit', $i );
		
		switch( $strategy ) {
		case 'split':
			preg_split( $pattern, $subject );
			break;
		case 'match':
			preg_match( $pattern, $subject );
			break;
		case 'match_all':
			$matches = array();
			preg_match_all( $pattern, $subject, $matches );
			break;
		}

		ini_set( 'pcre.backtrack_limit', $saved_config );

		switch( preg_last_error() ) {
		case PREG_NO_ERROR:
			return $i;
		case PREG_BACKTRACK_LIMIT_ERROR:
			continue;
		case PREG_RECURSION_LIMIT_ERROR:
			trigger_error('PCRE recursion limit encountered before backtrack limit.');
			return;
		case PREG_BAD_UTF8_ERROR:
			trigger_error('UTF-8 error during PCRE benchmark.');
			return;
		case PREG_INTERNAL_ERROR:
			trigger_error('Internal error during PCRE benchmark.');
			return;
		default:
			trigger_error('Unexpected error during PCRE benchmark.');
			return;
		}
	}

	return $i;
}