Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Katie Maher
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Katie Maher

The CFParam Tag Doesn't Care About White-Space In ColdFusion

By Ben Nadel on
Tags: ColdFusion

For months, I've been trying to track down what I thought was a Cookie problem at InVision App. Every now and then, we'd start logging thousands upon thousands of cookie errors. Finally, I realized that it wasn't a problem with the cookie itself, per-say, but rather with the fact that the ColdFusion CFParam tag doesn't really care about white-space.

To demonstrate this, we can execute a CFParam tag with embedded white-space and then look at how the data structures are mutated:

  • <cfscript>
  •  
  • // Creating a white-space variable for more obvious injection.
  • __ = repeatString( " ", 10 );
  •  
  • // Param a struct-key with embedded white-space.
  • param name="#__#url#__#.#__#foo#__#" type="string" default="bar";
  •  
  • // Output the value of the non-white-space version.
  • writeOutput( "foo: " & url.foo );
  •  
  • </cfscript>

Here, you can see that I am including 10 spaces before and after each token in the CFParam expression. However, after the param tag has been executed, I'm looking up the value using trimmed references:

foo: bar

As you can see, the white-space embedded in the Name expression had no bearing on the values involved. This is the same way that white-space has very little bearing on how the rest of your code is compiled and executed. This is correct. This is proper tokenization of the code.

But, it did trip us up when it came to setting cookies. Somewhere in the codebase, we had a little piece of control flow that was paraming a cookie value based on another variable value. We were using the CFParam tag to setup the default and then subsequently referencing the cookie key later on in the same pathway. It looked something like this:

  • <cfscript>
  •  
  • // Creating a white-space variable for more obvious injection.
  • __ = repeatString( " ", 10 );
  •  
  • // Define a cookie name with TRAILING white-space.
  • cookieName = "foo#__#";
  •  
  • // Param the cookie value.
  • param name="cookie.#cookieName#" type="string" default="bar";
  •  
  • // Check to see if the param'd cookie value exists.
  • writeOutput( "Cookie exists: " & structKeyExists( cookie, cookieName ) );
  •  
  • // Check for a version with no white-space.
  • writeOutput( "<br />" );
  • writeOutput( "foo exists: " & structKeyExists( cookie, trim( cookieName ) ) );
  •  
  • </cfscript>

As you can see, the cookie "name" in this case has trailing white-space. Now, cookie names can't have white-space (or commas or semi-colons or non-ASCII values). So, you might have expected this code to throw an error. But, since we were using the CFParam tag to setup the default value, the trailing white-space, on the key-name, was essentially being ignored during execution. As such, the value was stored in a cookie key that was being implicitly trimmed.

However, since the cookie name contained trailing white-space according to the variable, cookieName, subsequent references to the cookie scope would throw the following ColdFusion error:

Element XYZ is undefined in a Java object of type class coldfusion.runtime.CookieScope

This is why the first structKeyExists() fails (uses key with trailing spaces) and the second structKeyExists() succeeds (uses trimmed key):

Cookie exists: NO
foo exists: YES

Nothing here is buggy except for, perhaps, the approach we were using. But, you can certainly imagine that a trailing space was next to impossible to even see in the logging output. Oh well, you live and you learn - at least I finally figured out what the heck was going wrong. That's thousands of errors that will stop showing up in Kibana!




Reader Comments

I rather think it is buggy, Ben. CFPARAM is not supposed to trim. That it *does* trim is a bug. It should just do what it's told to do, with the values it's been given. It should not be second-guessing stuff like this.

Did you by any chance check your code on Lucee?

Cheers for writing this up, fella.

Reply to this Comment

I generally log variable outputs surrounded by single quotes or square brackets (something) so I can see things like unexpected leading our trailing spaces

Reply to this Comment

@Chris,

Yeah, that's a a great practice. I do that when I am explicitly throwing errors. But, this was an unhandled error that was being generically logged. Oh well, next time!

Reply to this Comment

In case anyone comes across this as I did during a migration to Lucee. In Lucee the whitespace in a parameter name is not ignored.

So CF 8 for me this was OK

<cfparam name="xsubtitlex " default="">
#xsubtitlex#

but in Lucee an exception is thrown.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.