Support » Plugin: Hackadelic SEO Table Of Contents » Plugin options corruption results in empty post content

  • Well, these were fun several hours…

    Earlier today, our site,, suddenly started returning no post content for every post. The list pages have content, but once you click in – nada.

    After frantically trying to look at the obvious things and disabling the usual suspects, like caching plugins, I dug in deeper with a PHP debugger (love you, PHPEd) and an inactive production web server set up for debugging.

    What I found after digging is that the content was retrieved OK, but after the_content filter was applied, was reset to an empty value. Digging around some more, I finally narrowed it down to Hackadelic TOC as the culprit.

    The cause was a weird reset of plugin options to blank, and more specifically “Maximum Heading Level” to 0 instead of the default 4.

    In the logs, I saw:

    [03-Jun-2014 03:29:10 UTC] PHP Warning:  preg_replace_callback(): Compilation failed: range out of order in character class at offset 6 in wp-content/plugins/hackadelic-table-of-content-boxes/hackadelic-toc.php on line 185

    The function in question:

    function collectTOC($content) {
        $this->headers = array();
        $this->tocID = 0;
        $this->shortcodeWasHere = false;
        if ( !is_single() && !is_page() ) return $content;
        $n = $this->MAX_LEVEL;
        $pattern = '@<h([1-'.$n.'])(\s+.*?)?'.'>\s*(.+?)\s*</h\1>@i';
        $callback = array(&$this, 'doHeader');
        global $multipage, $numpages, $pages, $page;
        for ($i = 1; $i <= $numpages; $i++) {
          if ($i == $page) { $in = $content; $out =& $content; $this->url = ''; }
          else { $in = $pages[$i-1]; unset($out); $this->url = $this->urlToPageNr($i); }
          $out = preg_replace_callback($pattern, $callback, $in);
        return $content;

    Looking at the regex, the value of $n is 0 due to reset settings, and the whole expression [1-0] ended up invalid. As it turns out, that takes the whole $content with it and it ends up blank.

    I’m not exactly sure how it got reset – my money is on a race condition while restarting memcached (W3 Total Cache object caching is on, and it caches wp_options into memcached). There are some places in Hackadelic TOC where options could potentially be written to the database in this case and consequently reset, even though nobody is modifying its settings through wp-admin.

    The following fix prevents this bug from breaking the whole site if plugin options were to get reset once again for some reason:

    Insert after $n = $this->MAX_LEVEL;

    /* Tweak by Artem: Somehow, settings could get corrupt, and when they do, $n gets assigned to 0.
           This happens to break EVERYTHING because the regex becomes invalid and returned $content becomes null */
        if ($n < 1) {
          $n = 4;

    Phew, now to reply to dozens of tweets, G+ messages, Facebook messages, and emails I received in the last few hours about this total clusterquack.

    I know the plugin isn’t really being updated anymore, but it may help someone else (maybe even me when I forget all about this), so I’m documenting it here.

Viewing 1 replies (of 1 total)
Viewing 1 replies (of 1 total)
  • The topic ‘Plugin options corruption results in empty post content’ is closed to new replies.