{"id":40,"date":"2007-12-07T12:33:16","date_gmt":"2007-12-07T14:33:16","guid":{"rendered":"http:\/\/www.ragestorm.net\/blogs\/?p=40"},"modified":"2007-12-07T16:04:39","modified_gmt":"2007-12-07T18:04:39","slug":"never-trust-your-input-a-wordpress-case","status":"publish","type":"post","link":"https:\/\/www.ragestorm.net\/blogs\/?p=40","title":{"rendered":"Never Trust Your Input &#8211; A WordPress Case"},"content":{"rendered":"<p>\u00a0Although this post isn&#8217;t about Security, the title still holds true about everything you do with input, but whatever you do, never trust it. :)<\/p>\n<p>While I was manually editting the last post about SQL I encountered a bug in WordPress. This is not a big deal, probably because it&#8217;s not a security bug, but it&#8217;s really annoying when the browser freezes while you&#8217;re trying to edit your post. So I switched to FireFox and the same bug happened again. In the beginning I thought something was wrong in the internals of the browsers, but both browsers have the same internal bug? That doesn&#8217;t make much sense. Looking at the Task Manager I saw that both IE and FF chew up memory and CPU at 50% (this is because I have two cores, otherwise it would be 100% on a single processor&#8230;). So immediately I understood that there&#8217;s an infinite loop running, hence the 50% CPU usage and it allocates memory in a way (eventually by strings). Next thing I did was to isolate the code of WordPress\u00a0somehow, I wasn&#8217;t even sure what caused this bug to surface in the beginning. All I knew was that it has something to do with my post. Therefore I needed to take a look at my raw post&#8217;s text, since\u00a0it contained some HTML tags. So eventually I saw that I had an unbalanced PRE tag. Unbalanced means that I add an opener tag but didn&#8217;t close it. So left only a &#8220;&lt;pre&gt;&#8221; in my post and saw that the browsers freeze. Now what? Digging into WordPress code I understood there is a special class for a textarea input. I realized I have to search for a &#8220;pre&#8221; string in the JS files (which originated from .php files). And eventually after a few trials and errors of uncommenting code I found this chunk:<\/p>\n<p>var startPos = -1;<br \/>\nwhile ((startPos = content.indexOf(&#8216;&lt;pre&#8217;, startPos+1)) != -1) {<br \/>\n\u00a0\u00a0\u00a0 var endPos = content.indexOf(&#8216;&lt;\/pre&gt;&#8217;, startPos+1);<br \/>\n\u00a0\u00a0\u00a0 var innerPos = content.indexOf(&#8216;&gt;&#8217;, startPos+1);<br \/>\n\u00a0\u00a0 \u00a0var chunkBefore = content.substring(0, innerPos);<br \/>\n\u00a0\u00a0 \u00a0var chunkAfter = content.substring(endPos);<br \/>\n\u00a0\u00a0\u00a0 var innards = content.substring(innerPos, endPos);<\/p>\n<p>\u00a0\u00a0 innards = innards.replace(\/\\n\/g, &#8216;&lt;br \/&gt;&#8217;);<br \/>\n\u00a0\u00a0 content = chunkBefore + innards + chunkAfter;<br \/>\n\u00a0 }<\/p>\n<p>This is ripped from the tiny_mce_gzip.php file. The &#8216;content&#8217; variable holds the text of my post, which is &#8220;&lt;pre&gt;&#8221;. Now notice the first line in the block:<\/p>\n<p>var endPos = content.indexOf(&#8216;&lt;\/pre&gt;&#8217;, startPos+1);<\/p>\n<p>Which renders endPos to be -1, since there&#8217;s no close tag. And more over, there is no <strong>check<\/strong> for the return value, the programmer assumed it will always find a match. :(<br \/>\nNow let&#8217;s analyze the block to see why it becomes an infinite loop that chews up memory:<\/p>\n<p>endPos = -1, innerPos = 4, chunkBefore = &#8220;&lt;pre&#8221;, chunkAfter = &#8220;&lt;pre&gt;&#8221;, innards = &#8220;&lt;pre&gt;&#8221;;<\/p>\n<p>Notice that &#8216;innards&#8217; contain the whole content, since evaluating a substring with an input of -1 returns the input untouched&#8230; We can ignore the replace, which doesn&#8217;t really affect the loop in any way here. And be hold, &#8216;content&#8217; is being reassigned to hold the whole new string but now it looks like: &#8220;&lt;pre&lt;pre&gt;&lt;pre&gt;&#8221;.<\/p>\n<p>And the loop stop condition of &#8216;startPos&#8217; returns true and again endPos gets -1&#8230; And bam, you&#8217;re browser is frozen.<\/p>\n<p>The fix is pretty straight forward. It&#8217;s a shame they have a stupid bug like this. What I had to do at my end was to use phpMyAdmin to edit the SQL tables and change the post so it won&#8217;t lock my browser yet again. Although I could have fixed this bug on the server, for some reason I didn&#8217;t do it&#8230;<\/p>\n<p>Anyway I sent an email to WordPress and hopefully they will fix it immediately, though it&#8217;s nothing urgent.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00a0Although this post isn&#8217;t about Security, the title still holds true about everything you do with input, but whatever you do, never trust it. :) While I was manually editting the last post about SQL I encountered a bug in WordPress. This is not a big deal, probably because it&#8217;s not a security bug, but [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":""},"categories":[1],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pbWKd-E","_links":{"self":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/40"}],"collection":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=40"}],"version-history":[{"count":0,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/40\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=40"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=40"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}