ColdFusion 2018 does not interpret undefined as empty string - coldfusion

A ColdFusion server has been updated to ColdFusion 2018 (from ColdFusion 9 or 11).
One of the oldest applications on that server contains code like: < cfif arguments[key] NEQ "">
Before, this seems to have been equivalent to isDefined("arguments.key") or StructKeyExists(arguments, key).
Today, even though isDefined("arguments.key") is false, and StructKeyExists(arguments, key) is also negative, <cfif arguments[key] NEQ ""> fails, because arguments[key] doesn't behave like empty string anymore. In fact, < cfdump var="#arguments[key]#"> displays 'undefined'.
Is there anything I can do in order to avoid changing the code everywhere where empty string was used instead of StructKeyExists? Perhaps a ColdFusion server parameter? (THIS.enableNullSupport didn't help)

The bracket notation for the ARGUMENTS scope will always return an undefined value for non-existing keys and values in all versions of Adobe ColdFusion.
function f() {
return arguments[key];
}
f(); // returns undefined
function f() {
return arguments["key"];
}
f(); // returns undefined
function f() {
return arguments.key;
}
f(); // throws exception: Element KEY is undefined in ARGUMENTS
All 3 cases should throw an exception. This is inconsistent and should be treated as a bug. It is probably only kept for backwards compatibility.
Anyway, as you already noticed:
// ACF 10
(undefined eq "") -> TRUE
// ACF 11
(undefined eq "") -> TRUE
// ACF 2016
(undefined eq "") -> TRUE
// ACF 2018
(undefined eq "") -> FALSE
// ACF 2021
(undefined eq "") -> TRUE
Adobe introduced NULL support in ACF 2018 and broke this behavior. They fixed it in ACF 2021, but not in ACF 2018, classic Adobe move.
Either report this bug to Adobe and hope for an update (last bugfixing for ACF 2018 was done in November 2019, so good luck) or fix your old application by not relying on this dodgy function argument check.

IsDefinedValue may help as it's agnostic to NULL and checks a value exists too.
https://cflib.org/udf/isDefinedValue

Related

Delphi 10.1 - Wrong Match.Value in TMatchEvaluator when calling TRegEx.Replace()

I've found one bug with latest Delphi 10.1 Berlin (and in 10.2 Tokyo too).
If you call TRegEx.Replace with TMatchEvaluator specified, you may got wrong TMatch inside Evaluator function. In Delphi XE-XE5 it seems works good.
Evaluator:
function TForm1.EvaluatorU(const Match: TMatch): string;
var
lChar: Word;
lMatchVal: string;
begin
Result := '';
lMatchVal := Match.Groups[1].Value;
lChar := StrToIntDef('$'+lMatchVal, 0);
if lChar <> 0 then
Result := Char(lChar);
end;
Call:
Result := TRegEx.Replace('\u0418\u0443, \u0427\u0436\u044d\u0446\u0437\u044f\u043d', '\\u([0-9a-f]{4})', EvaluatorU, [roIgnoreCase]);
First call of Evaluator will bring right TMatch.Value (or TMatch.Group[].Value) context, but second call will bring wrong Match.Value to callback function(
Do you have some idea about workaround?
I going to check this issue on TPerlRegEx class, maybe something wrong is in wrapper (TRegEx) functions.
Update: with TPerlRegEx Replacement with callback function (OnReplace) works good...
Update2: it seems there is a bug in TPerlRegEx. It returns wrong GroupOffsets. On First call of OnReplace callback this value is correct. Next calls returns +1 offset more than needed. But call of TPerlRegEx.Groups returns correct subgroup value...
Last update and solution found:
I've found a problem in TPerlRegEx.UTF8IndexToUnicode function optimization.
There are LastIndex*/LastIndexResult* fields used to optimize sequential call of function with same params. But after replacement made via callback functions and when MatchAgain is called into TPerlRegEx.ReplaceAll function, this can make a bad trick(
Simple solution is copy System.RegularExpressionsCore.pas from \source\rtl\common to your project directory and replace call of TPerlRegEx.UTF8IndexToUnicode to deprecated unoptimized UTF8IndexToUnicode function... Or clear this internal fields somewhere in ClearStoredGroups function for example.
upd. Here is my embarcadero quality central issue.

FW/1 not finding controller

I recently updated my FW/1 app to version 3.5 and now the controllers functions aren't being called.
<!---# Version History: 11 July 2011, Created by James Mohler --->
<!---# Version History: 31 May 2013, Converted to Component by James Mohler --->
component accessors=true {
property framework;
property beanFactory;
property reportService;
property historyService;
property uiService;
property payService;
property supportService;
void function before(required struct rc) {
param rc.BossEID = "all";
Dump of variables
Note that there are no functions on the controllers. No error message is shown.
The ColdFusion style comments seems to change how the file is processed.
component accessors=true {
doesn't do anything because the file is not in automatic <cfscript> mode.

queryExecute ColdFusion syntax vs Railo/Lucee syntax

I have a bunch of code that has been written against a Railo server. We are now trying to move some of that code over to a CF11 box and a Lucee box.
I have been using queryExecute like this:
rt = queryExecute(
sql = 'select *
from translation
where translationID = :translationID
and translatedStr = :translatedStr'
, params = {translationID: arguments.translationID
, translatedStr: arguments.translatedStr}
, options= {datasource: application.ds}
);
I was under the impression that the syntax was the same on CF11 but I am getting an error :
Parameter validation error for the QUERYEXECUTE function.
A built-in ColdFusion function cannot accept an assignment statement as a parameter,
although it can accept expressions. For example, QUERYEXECUTE(d=a*b) is not acceptable.
The above executeQuery works fine on Lucee. I am going to need to go through the whole code base and make it work on both CF11 AND on Lucee.
Can someone, who is more familiar with ACF, tell me what is the best way to do this. It appears that ACF is having trouble with the param names. If I remove sql = and params = that takes away some of the problem, although I like the readability of having them named. Also it appears that ACF doesn't like translationID: arguments.translationID and wants me to change it too translationID = arguments.translationID. I just want to make sure that there isn't something I am missing before I go through the time consuming process of making all the changes.
Pretty sure your parameters need to be in the form of a structure to include the value (and query param if you so choose).
Try this:
rt = queryExecute(
"select *
from translation
where translationID = :translationID
and translatedStr = :translatedStr",
{
translationID: {value: arguments.translationID},
translatedStr: {value: arguments.translatedStr}
},
{datasource: application.ds}
);
Well the error message is pretty clear, isn't it?
A built-in ColdFusion function cannot accept an assignment statement
as a parameter, although it can accept expressions. For example,
QUERYEXECUTE(d=a*b) is not acceptable.
And you have this:
queryExecute(
name = value
, name = value
, name= value
)
Which the error message says isn't allowed.
You just need to get rid of the names of your args. In-built CFML functions don't work like that. It's a compat bug in Lucee that it does support this.

Undefined error when using CFThread in Custom Tags in ColdFusion 10

NOTE: I have completely rewritten this question to take into account new information. Please reread if you've already been through this one.
I'm getting errors when using a cfthread from within a custom tag in ColdFusion 10. In the Application log, I get the following entries:
Variable _cffunccfthread_cfThreadTag2ecfm16902001291 is undefined.
The name of the function it's returning as an error is _cffunccfthread_cf[Page Name Calling the CFThreadTag] then a number that doesn't change from request to request. I can duplicate this every time with the following code:
Application.cfc:
component
{
this.name = "CFThreadCustomTagTest";
}
ThePage.cfm:
<cfthread action="run" name="ThreadTestInPage">
<cflog log="Application" text="The thread in the page successfully ran" type="information" />
</cfthread>
<cf_ThreadTag />
ThreadTag.cfm:
<cfif thisTag.ExecutionMode EQ "start">
<cfthread action="run" name="ThreadTest">
<cflog log="Application" text="The thread within the tag successfully ran" type="information" />
</cfthread>
</cfif>
Just drop all three files in a directory in ColdFusion 10 and load ThePage.cfm. I get the following entries in the Application log:
"Severity","ThreadID","Date","Time","Application","Message"
"Information","ajp-bio-8012-exec-1","06/19/12","07:18:11",,"C:\ColdFusion10\cfusion\logs\application.log initialized"
"Information","cfthread-11","06/19/12","07:18:15","CFTHREADCUSTOMTAGTEST","The thread in the page successfully ran"
"Error","cfthread-9","06/19/12","07:18:15",,"THREADTEST: Variable _cffunccfthread_cfThreadTag2ecfm16902001291 is undefined. "
I also noticed that in the error for the thread within the custom tag, it does not contain the application name. While the log entry for the thread in the page does. Notice that the error line simply has ,, for the Application column of the log, while the successful thread has "CFTHREADCUSTOMTAGTEST".
If I change ThreadTag.cfm to wait for the thread within the tag to finish processing, then everything works fine, and I get the two entries in the log as I expect:
<cfif thisTag.ExecutionMode EQ "start">
<cfthread action="run" name="ThreadTest">
<cflog log="Application" text="The thread within the tag successfully ran" type="information" />
</cfthread>
<cfthread action="join" name="ThreadTest" timeout="10" />
<cfdump var="#cfthread#">
</cfif>
And to verify that there are no funky settings anywhere, here's my local development environment's settings summary.
So it seems that if I just throw the thread out there, and don't wait for it to finish, then the thread seems to be looking for something from the parent page that is no longer in memory. At least that's my completely unfounded guess :).
I've also filed a bug with Adobe. Bug number 3218452.
I understand your predicament, but there's no actual question here.
Basically you've found a bug in CF. A few people - myself included - can replicate it.
No-one's missing anything, except for the Adobe engineers who missed including this sort of thing in their regression testing when implementing CF10. That's no indictment of them, really, as I think this is reasonably edge case, perhaps?
The "variable" CF ain't finding is actually the name of the compiled class that the CF compiler makes when compiling the code. It looks like there's a compiler bug to me.
For example, my error is this:
THREADTEST: Variable _cffunccfthread_cfThreadTag2ecfm13713410591 is undefined.
However the compiled class is:
cfThreadTag2ecfm1371341059$func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591.class
I don't know what part of the class name the variable is supposed to be named for, but I suspect it should be looking for func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591. Or on the other hand the compiler should not be compiling the ThreadTag.cfm file as a FUNCTION? But I'm guessing... it might need to compile the thread code as a function so as to call it in a separate thread? That's a guess. Either way: it's compiling the code as one thing, and then looking for a different thing. because of a bug.
But bottom line here: yep, you've found a bug. And you've flagged it with Adobe. I dunno what else there is for you to do here?
So basically we now know one cannot have a <cfthread> call in a custom tag (I also tested via <cfmodule>: same problem). You're gonna have to write yer code a different way, using an include or a method or something. Less than ideal, I know, but what can you do?
Footnote:
I looked at the compiled code and it looks like the problem is CF is compiling the class with that func_ prefix, but it's referring to it in its code without. I didn't follow the code all the way to checking everything that's happening, but it looks to me like there are references to it trying to load _cffunccfthread_cfThreadTag2ecfm13713410591 rather than the correct name: func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591.class.
Dan,
Please look on this page:
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec0b2e1-7ff0.html
And this section "Determining the tag execution mode"
And try the equivalent mode check code <cfswitch expression=#thisTag.ExecutionMode#>
To see if this causes a different compiler code gen. Maybe it will gen code a bit different and the variable will get generated.
Also, another test to try is to put you tag first in "ThePage.cfm" and see if that causes a different code gen as well.
Finally, are you on a newer JVM, as newer ones use the latest Fork/Join features of the Java concurrency approach such as Futures, etc. and they may be causing different code gen. Maybe set your JDK to an older one and see if the code gen is different.
No real answer, but some things to look at.
I ran into this as well.
My solution was to refactor and put the cfthread stuff into a .cfc and call that from the .cfm page.

Coldfusion: conflicting cfdump statements

I have a query l.q. l is var scoped:
var l = {};
If I dump l:
writeDump(var:l, abort:true);
I get
You can see that q (l.q) shows [undefined struct element]. However if I do:
writeDump(var:isQuery(l.q), abort:true);
I get yes as the output? Dumping l.q.recordCount returns 1.
If I dump l.q I get an error: Error Type java.lang.ArrayIndexOutOfBoundsException : [N/A].
This is causing me quite a headache as on my website I get variables randomly disappearing like this all the time.
Any ideas of what could be going on here? CF9.0.1 Ent running on Windows Server 2005.
It looks like whatever is populating your l.q variable is not working correctly. How is l.q being populated?
If you're using l = {} as a "local" scope replacement - don't ColdFusion 9 already has a local scope inside of functions and you can dump it.
Are these dumps in the same place? Remember that if you execute a query that does not return anything (such as an update or delete) but use the name parameter, that variable will be set to undefined. It sounds like this could be happening here.