{"id":441,"date":"2012-01-30T19:26:51","date_gmt":"2012-01-31T03:26:51","guid":{"rendered":"http:\/\/kagan.mactane.org\/blog\/?p=441"},"modified":"2013-06-08T11:14:58","modified_gmt":"2013-06-08T18:14:58","slug":"beware-of-optional-curly-braces-they-will-bite-you","status":"publish","type":"post","link":"https:\/\/kagan.mactane.org\/blog\/2012\/01\/30\/beware-of-optional-curly-braces-they-will-bite-you\/","title":{"rendered":"Beware of Optional Curly Braces&nbsp;&mdash; They Will <em>Bite<\/em> You"},"content":{"rendered":"<p>I was looking through some PHP code from a third-party vendor recently, and saw something that made my jaw drop. It&#8217;s pretty innocent-looking, at first. Here&#8217;s a somewhat anonymized and genericized version of the code, but the thing that bothered me is still intact. It&#8217;s not really a bug, <i>per&nbsp;se<\/i>; the code will function as intended.&nbsp;But&#8230;<\/p>\n<div class=\"code\">$currentRow = 0;<br \/>\n$itemId = &#34;&#34;;<br \/>\n$index = 0;<br \/>\nwhile ($row = mysql_fetch_object($result)) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($currentRow == 10) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderHeaderRow();<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$currentRow = 0;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ takes an itemId and displays relevant columns<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderSummaryRow($row->itemId);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$currentRow++;<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($index > 0)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$itemId .=  &#34;,&#34;;    # interpolate a comma<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$itemId .= $row->itemId;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$index++;<br \/>\n}<\/p><\/div>\n<p>See the problem? Really, there are a few ways this can go wrong. To a quick glance, the only clue that line&nbsp;14 (&#8220;interpolate a comma&#8221;) is part of a conditional is its indentation. The indentation is important to a human reader&nbsp;&mdash; but <strong>absolutely irrelevant<\/strong> to the PHP interpreter, which simply treats the next line after the conditional as the conditional&#8217;s block. Regardless of how it&#8217;s indented, and regardless of what else is&nbsp;around.<\/p>\n<p><em>The way it looks to a human <strong>is not<\/strong> the way it looks to the&nbsp;machine.<\/em><\/p>\n<p>What happens if someone wants to add some logging? What if they add it after the comma&nbsp;line?<\/p>\n<div class=\"code\">if ($index > 0)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$itemId .=  &#34;,&#34;;    # interpolate a comma<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLog(&#34;Added a comma&#34;);<br \/>\n$itemId .= $row->itemId;<br \/>\n$index++;<\/div>\n<p>Now the log claims the code has added a comma, even when it hasn&#8217;t. But still, it could be worse! What if you decided to add your logging <em>before<\/em> the other&nbsp;line?<\/p>\n<div class=\"code\">if ($index > 0)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLog(&#34;Adding a comma to itemId.&#46;.&#34;);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$itemId .=  &#34;,&#34;;    # interpolate a comma<br \/>\n$itemId .= $row->itemId;<br \/>\n$index++;<\/div>\n<p>Now it adds a comma no matter what&nbsp;&mdash; even the first time through the loop, when the string is empty. So instead of a string like <code>'123,124,125'<\/code>, $itemId will now have a leading comma: <code>',123,124,125'<\/code>. Since this value is getting stitched into a SQL query later on, it means your app will blow up with a SQL syntax&nbsp;error.<\/p>\n<p>This is why Python makes whitespace significant to program flow. The way the indentation makes it <em>look like<\/em> the logical structure is, is how the structure <em>actually<\/em>&nbsp;is.<\/p>\n<p>And this is also why Perl&nbsp;&mdash; of all languages, one that normally errs on the side of letting you leave out anything that can be inferred from context&nbsp;&mdash; <strong>Perl<\/strong> insists in its syntax documentation that <a href=\"http:\/\/perldoc.perl.org\/perlsyn.html#Compound-Statements\">in cases like this<\/a>, &#8220;the curly brackets are <em>required<\/em>&nbsp;&mdash; no dangling statements allowed.&#8221; (It then says, in typically Perlish fashion: &#8220;If you want to write conditionals without curly brackets there are several other ways to do it.&#8221;)<\/p>\n<p>If you&#8217;re working in one of those languages that lets you omit curly braces around a single-statement conditional&nbsp;&mdash; <strong><em>DON&#8217;T DO IT!<\/em><\/strong> The potential maintenance and debugging problems are <em>not<\/em> worth the fun of saving two keystrokes (or just one, if you work in an editor that auto-closes your braces for&nbsp;you).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was looking through some PHP code from a third-party vendor recently, and saw something that made my jaw drop. It&#8217;s pretty innocent-looking, at first. Here&#8217;s a somewhat anonymized and genericized version of the code, but the thing that bothered me is still intact. It&#8217;s not really a bug, per&nbsp;se; the code will function as [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[63,7,5,82],"_links":{"self":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/441"}],"collection":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/comments?post=441"}],"version-history":[{"count":3,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/441\/revisions"}],"predecessor-version":[{"id":561,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/441\/revisions\/561"}],"wp:attachment":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/media?parent=441"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/categories?post=441"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/tags?post=441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}