Sunday, January 18, 2015

Bedrock + Barewords = Bug

This morning, after being sufficiently caffeinated with a full pot of coffee, I was able to isolate a Bedrock bug that has been bugging me.  Bedrock was failing to throw an exception on what I would consider a syntax error (missing right end tag >).  

  <null:foo $baz.some_method()
  <var $foo>

Bedrock however, happily parsed the expressions and went along it's merry way...argghhh!

Is it a bug in Bedrock?  Probably, but IMHO it's really a problem with Bedrock's loosely defined grammar.

Consider this assignment:

  <null:foo ok>

...which is perfectly ok to do, I (and Bedrock) suppose...and so is:

  <null:foo 'ok'>
  <null:foo "ok">
  <null:foo q{ok}>

Danger! Danger Will Robinson! Danger!
In Perl parlance, <null:foo ok> might be considered a bareword assignment and is generally frowned upon and DANGEROUS and potentially ambiguous for various reasons.

  $ perl -e '$a = foo; print $a;'

You really don't want to use bareword assignments I guess, unless you really know what you are doing and you sprinkle in a comment.

Now consider again our typo (missing end tag > ):

  <null:foo $baz.some_method()
  <var $foo>

Well...guess how Bedrock interprets this expression? 

Bedrock thinks this is an assignment of foo with three terms, hence Bedrock wants to create an array of three items which are:

  1.  $baz.some_method() the result of a method call
  2.   <var  a bareword - rhu roh!
  3.   $foo  a scalar
Ruh Roh!
Since Bedrock seems to allow barewords beginning with <, the second item, <var is considered a bareword in the newly created array.

However, there are certain characters that Bedrock does recognize as special when they begin a new term - for example the sigil $ or a ( to start an expression.

Clearly we need to tighten up what Bedrock considers a bareword or disallow barewords altogether.

Hold on there skippy...let's not break any older code!  We need to preserve compatibility.

Today's patch therefore, restricts the use of two new characters to start barewords (< and >).

Ultimately, as almost all bugs go, this one required more digging and testing then actual coding...the diff for TagX::Parser:

  -  elsif (s/^([^\s\x28\x29\x2c]+)//) {
  +  elsif (s/^([^\s\x28\x29\x2c\x3c\x3e]+)//) {

Okay, so now Bedrock will throw more exceptions.  Yippee!!

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.