Uploaded image for project: 'phpBB3'
  1. phpBB3
  2. PHPBB3-9720

BBcodes not parsed if message grows over 100000 characters while BBcode-UID is appended

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 3.0.7-PL1
    • Fix Version/s: 3.2.0
    • Component/s: BBCode Engine, Posting
    • Labels:
      None
    • Environment:
      PHP 5.3.1, MySQL 5.1.41, Opera 10.54 / Firefox 3.0.5

      Description

      Problem: If e.g. we have a posting text of 76524 characters which includes 359 pairs of [URL=..][IMG] tags and then is encapsulated in one [U] tag phpBB will fail to parse the [U] tag.

      Reason: while processing the text each tag gets a UID appended, so the text grows - and at some point exceeds 100000 characters. After this point no more tags get parsed, since all preg_xxx() functions won't give any result (because internally PREG fails). Most PHP settings default to have a PREG backtrace limit of 100000 characters and phpBB never calls preg_last_error() to check for failures (note: failures, not regexp pattern errors).

      Workaround: in "/includes/message_parser.php" function parse_bbcode()'s core goes like this:

      foreach ($bbcode_data['regexp'] as $regexp => $replacement)
      {
      	// The pattern gets compiled and cached by the PCRE extension,
      	// it should not demand recompilation
      	if (preg_match($regexp, $this->message))
      	{
      		$this->message = preg_replace($regexp, $replacement, $this->message);
      		$bitfield->set($bbcode_data['bbcode_id']);
      	}
      }

      To check for PREG failures we can already check preg_match() since this also fails once the text length exceeds the limit. If we only check for a backtrack limit failure we can try to increase the limit for a couple of times. How often and in which steps we increment the limit might be subject of another discussion:

      foreach ($bbcode_data['regexp'] as $regexp => $replacement)
      {
      	$iSet= 0;  // How often did we set a new limit
      	while( $iSet< 10 ) {  // On default values like 100000 the highest new limit would be 250000
      		// The pattern gets compiled and cached by the PCRE extension,
      		// it should not demand recompilation
      		if (preg_match($regexp, $this->message))
      		{
      			$this->message = preg_replace($regexp, $replacement, $this->message);
      			$bitfield->set($bbcode_data['bbcode_id']);
      		}
       
      		if( preg_last_error()== PREG_BACKTRACK_LIMIT_ERROR ) {  // Only check for backtrack limit failure
      			ini_set( 'pcre.backtrack_limit', (int)ini_get( 'pcre.backtrack_limit' )+ 15000 );  // Get current limit and increase
      			$iSet++;  // Do not overkill the server
      		} else break;  // No fail, exit loop
      	}
      }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Marc Marc
                Reporter:
                AmigoJack AmigoJack
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: