tracker issue : CF-3595245

select a category, or use search below
(searches all categories and all time range)
Title:

Inline literal struct notation causes a Hibernate-related NPE when used as a named argument inside a non-braced if statement.

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/

Reporter/Name(from Bugbase): Peter Boughton / Peter Boughton (Peter Boughton)

Created: 07/15/2013

Components: Core Runtime

Versions: 10.0

Failure Type: Non Functioning

Found In Build/Fixed In Build: Final /

Priority/Frequency: Major / Most users will encounter

Locale/System: English / Platforms All

Vote Count: 2

Not using braces for a single-line if statement containing an function with an inline struct literal as an argument will, when OrmReload() is run, causes the compiler to fall over with a NullPointerError while Hibernate is scanning CFCs (even though the CFC isn't ORM related).

java.lang.NullPointerException at coldfusion.compiler.Treewalker.postorder(Treewalker.java:36) at coldfusion.compiler.Treewalker.postorder(Treewalker.java:27)

Full stack trace in attached file.

This code, inside a Coldbox handler, causes the java.lang.NullPointerException:
		if ( StructKeyExists(rc,'PersonTypeId') )
			rc.PersonType = PersonTypeService.findAllWhere( Criteria={PersonTypeId:rc.PersonTypeId} );

This doesn't:
		if ( StructKeyExists(rc,'PersonTypeId') )
			rc.PersonType = PersonTypeService.get( rc.PersonTypeId );

Causes NPE:
		if ( StructKeyExists(rc,'PersonTypeId') )
			rc.PersonType = PersonTypeService.get( A={id:rc.PersonTypeId} );

Doesn't cause NPE:
		if ( StructKeyExists(rc,'PersonTypeId') )
		{
			rc.PersonType = PersonTypeService.get( A={id:rc.PersonTypeId} );
		}

Doesn't cause NPE:
		// if ( StructKeyExists(rc,'PersonTypeId') )
			rc.PersonType = PersonTypeService.get( A={id:rc.PersonTypeId} );


(I've wasted enough time tracking down this problem; I don't feel like writing a self-contained demonstration.)

----------------------------- Additional Watson Details -----------------------------

Watson Bug ID:	3595245

External Customer Info:
External Company:  
External Customer Name: boughtonp
External Customer Email:  
External Test Config: 10,0,11,285437

Attachments:

  1. July 15, 2013 00:00:00: 1_cf_npe_stacktrace.txt

Comments:

Good work tracking it down as far as you did, Peter! +1, obviously. -- Adam
Vote by External U.
14954 | July 15, 2013 12:32:46 PM GMT
Passing inline struct as positional arguments inside if/while block works fine. And the source code doesn't have any observable NPE issue. We would need some repro-able test case to fix this.
Comment by Chandan ..
14952 | November 05, 2013 07:51:44 AM GMT
I got this, too. I was getting it when I had something like this: <cfif NOT foo(event = "user.registration.checkShoppingCartIDs", private = true, eventArguments={returnAjax: arguments.returnAjax}) /> .... </cfif> But when I stored the result of the function call outside the if, the parse compile error didn't occur: <cfset local.returnValue = foo(event = "user.registration.checkShoppingCartIDs", private = true, eventArguments={returnAjax: arguments.returnAjax}) /> <cfif NOT local.returnValue /> .... </cfif> Looking into it deeper, I could only find that it occurs when we pass an inline struct to a function as part of an if-expr inside an if adjacent to another if. Consider the following code, which will crash upon compile, even if the first if-block does something on the inside. If you remove the first if block, everything compiles fine. <cfcomponent> <cffunction name="foo" access="public" returntype="void" output="false"> <cfset local.someBool = false /><!---This can be dynamic, such as local.someBool = arguments.someArg; value doesn't appear to matter as I will demonstrate next. ---> <cfif local.someBool> </cfif> <cfif NOT local.someBool> <cfif foo2(someArgKey={})> </cfif> </cfif> </cffunction> </cfcomponent> You can simply further to something deterministic like the following. Yes, the code is silly. I only mention it here because it seems to be the simplist case that exemplifies the compile issue. It crashes, unless you remove some of the useless parts. In dynamic code, the issue is the same, just not so transparent. <cfcomponent> <cffunction name="foo" access="public" returntype="void" output="false"> <cfif false> </cfif> <cfif NOT false> <cfif foo2(someArgKey={})> </cfif> </cfif> </cffunction> </cfcomponent>
Comment by External U.
14953 | November 10, 2014 11:09:16 AM GMT
The fact that this crashes shows an inconsistency in the parser. Code that normally runs but doesn't when preceeded by certain constructs is strange and hard to avoid. Furthermore, crashes within the parser do not indicate where the line failed, which makes it difficult to track down in order to use a work-around.
Vote by External U.
14955 | November 10, 2014 12:15:09 PM GMT