Skip to main content
Participating Frequently
March 25, 2021
Answered

StructKeyExists function has issues with recent ColdFusion 18 updates

  • March 25, 2021
  • 4 replies
  • 2844 views

Complex object types cannot be converted to simple values. The expression has requested a variable or an intermediate expression result as a simple value. However, the result cannot be converted to a simple value. Simple values are strings, numbers, boolean values, and date/time values. I believe the issue is security related.

    This topic has been closed for replies.
    Correct answer Charlie Arehart

    I am using Windows Server 2016 OS and ColdFusion Build 2018.0.11.326016.


    Thanks for that, Khalid. And I have a work-around for this, finally. 

     

    First, I will get to trying things on Windows Server editions soon (again, to try to understand when this problem does and does not happen for different folks).

    But until then, the work-around is that it turns out that Adobe added a new applicaiton-level property called  sameformfieldsasarray, which controls this behavior. (I really thought I'd seen news of that before, but I could not find it when searching because of course that name is not so obvious. It means, in effect, "render multiple form fields of the same name, or with multuple values, as an array", which is exactly our issue here).

     

    And this update specifically changed that to be a default of true (see the technote for CF2018 update 11, for example, and how it points to the bug report CF-4211056, found at https://tracker.adobe.com/#/view/CF-4211056, which indicates the change). And see a comment I posted there with more, including pointing back to this.

     

    I'll note here that for those who want to try the setting, it's only shown there (and in the CF docs) as something that one would set in an application.cfc, using this.sameformfieldsasarray. For those not using application.cfc, note that it can ALSO be set on the cfapplication tag instead, modifying what you may use already in your application.cfm:

     

    <cfapplication name="whatever" sameformfieldsasarray="false" ... rest of your args>

     

     

    Sadly, there seems no way to set this behavior ONLY for a given cfm template, if that was of interest.

     

    Finally, beware NOT to just throw in a random new cfapplication tag on the cfm template with the form, in order to set this. Even if it may "work" in solving this problem, there could be other unexpected changes in behavior for your app by doing that. 

     

    I still look forward to understanding the variation some of us are seeing, even after applying the updates.

     

    And while the reporter of the bug above indicated that he saw different behavior based on WHETHER he was assessing the form variable within or outside of his application.cfm, in the example I offer above I was of course doing the code in its own template...and for what it's worth I had a blank application.cfm. I didn't think to mention that then, as I never fathomed it could matter. I just always put a blank application.cfm in a new folder I create with any test code, to make sure there's no impact of any application.cfm or cfc in a folder above that testing folder.)

     

    Khalid, let us know if this solution works for you (whether you use application.cfc or .cfm).

    4 replies

    Charlie Arehart
    Community Expert
    Community Expert
    March 28, 2021

    The answers offered below have focused on variations of Khalid's code, but with his code (and the variants) the problem is now apparent, and it's NOT what he proposed originally: it is not a problem with structkeyexists at all (it seems to me). Instead, it's a breaking change of behavior in the March 2021 updates for cf2021, 2018, and 2016, and that is undocumented, it seems. 

     

    What's changed is how CF processes form posts for fields having multiple values. Prior to the Mar updates, the form field would be available as a LIST of the multiple values, but after the updates instead they show being an ARRAY--which is unexpected, and would indeed break any apps that process fields with multiple values (like the structkeyexists Khalid was using). That's a RESULT rather than the CAUSE of the problem.

     
    See below for more, but I have opened a bug report about this: https://tracker.adobe.com/#/view/CF-4211444. If you agree (or disagree) with my contention, please add your vote (and/or comment) there.
     

    I have confirmed this with same code run against all 3 CF versions BEFORE last week's updates were applied and after. And FWIW, I have created a simpler form of the example Saurav offered, which demonstrates the point (see some more text to follow):

     

    Build - <cfoutput>#server.coldfusion.productversion#</cfoutput><br><br>
    <form name="f" action="" method="post" enctype="application/x-www-form-urlencoded">
        <select name="user" id="user" size="7" multiple="true">
            <option value="1" selected>user1</option>
            <option value="2" selected>user2</option>
            <option value="3" selected>user3</option>
        </select>
        <br><br>
        <input type="submit" value="Submit" name="submit">
    </form>
    <cfif isdefined("form.user")>
        <cfdump var="#form#"><br>
        <cfdump var="#isarray(form.user)#"><br>
    </cfif>
     
    Note I have added an isarray as well, which really asserts the point (but the content in the dump will show it). And if you may wonder why I don't use an islist also, it's because there is none. I just noticed that, and filed a feature request for it (and I acknowledge there why some would argue such is NOT needed). Please add your vote if you agree, or a comment if you do not.
     
    And in case someone wonders why to bother with the actual form submission when a cfparam could set default values, the problem again is in how CF is PROCESSING the forum submission, so you can't avoid doing the form submission to demonstrate the problem.
     
    And in case anyone would ask, I was doing the test against the built-in web server, so this is NOT about an issue with the web connector (or any need to update that). Indeed, I confirmed also that the problem happens EITHER with the built-in web server OR with the web connector (that was updated).
    /Charlie (troubleshooter, carehart. org)
    BKBK
    Community Expert
    Community Expert
    March 28, 2021

    @Charlie Arehart , I have ColdFusion 2021 Update 1. Your code sample runs without any error. Moreover, isarray(form.user) is False:

     

    Charlie Arehart
    Community Expert
    Community Expert
    March 28, 2021

    Well, I wouldn't have reported my observation if I'd not tested it. 🙂 Here's my screnshot below. We're indeed showing the same version (update and buld number). It's indeed curious.  So now we have to wonder about other differences. FWIW, I had tested it on Windows 10 Home and on the Adobe Docker images, with the browser being either Edge (Chromium) or Firefox (latest versions of all).

     

    But then curiously, I have tested on a different machine (happens to be Windows 10 Pro) and the problem does NOT happen there. I would be shocked that could make a difference. I will do more investigation, to find any other possible explanation. Again, below is my screenshot from the machine where I first identified this earlier today. Again, it fit really well as the explanation for what Khalid was saying. We still have not heard from him having tested either of the variants Saurav or I have offered. (Saurav, I have several comments on your blog post about the updates which remain unanswered.)

     

    BKBK, what OS are you running, and what browser, for your testing? And Khalid? And Saurav or anyone else who may try my example code? BTW, I had meant to simplify it still more (removing the name and enctype and the select size. I wanted to make it as simple as could be. I had done that, but somehow I copy/pasted here a variant from before I'd done all that.)

     
    /Charlie (troubleshooter, carehart. org)
    Community Manager
    March 26, 2021

    Khalid,

    Try this snippet and let us know:

    Build - <cfoutput>#server.coldfusion.productversion#</cfoutput><br><br>
    <cfset variables.users = querynew("user_id,user","Integer,Varchar",[[1,"user1"],[2,"user2"],[3,"user3"]])>
    <cfif isdefined("form.submit")>
        <cfdump var="#form#"><br>
    </cfif>
    <cfoutput>
        <cfform name="f" action="#cgi.script_name#">
            <select name="user" id="user" size="7" multiple="true">
                <cfloop query="#variables.users#">
                    <option value="#user_id#" <cfif structKeyExists(form, "user") and Listcontains(form.user,user_id)> selected</cfif>>#variables.users.user#</option>
                </cfloop>
            </select>
            <br><br>
            <input type="submit" value="Submit" name="submit">
        </cfform>
    </cfoutput>
    
    Charlie Arehart
    Community Expert
    Community Expert
    March 25, 2021

    Khalid, can you offer even a simple example, so we might confirm if we see what you do (on CF2018 update 17)?

    Also, are you sure NOTHING else changed in your environment? For instance, did anyone change the JVM that CF uses? If so, from what version to what version? That could be as much a cause of strange new errors, if one is not careful about how they do that.

    /Charlie (troubleshooter, carehart. org)
    Participating Frequently
    March 26, 2021

    Hello Charlie,

    When submitting multiple select values, it through exception at structKeyExists function, it works fine when passing a single select option value but produce error when passing more than one value to structKeyExists funtion.

    <select name="user" id="user" size="7" multiple="true">
    <cfloop query="#variables.users#">
    <cfoutput>
    <option value="#user_id#" <cfif structKeyExists(form, "user") selected</cfif>>#variables.users.user#</option>
    </cfoutput>
    </cfloop>
    </select>

    George____
    Inspiring
    March 26, 2021

    If that's a copy and paste you're missing a closing > after the "user")

    You can also do that with

    #structKeyExists(form,"user") ? 'selected' : ''#

    but you probably want to do this

    #structKeyExists(form,"user") AND form.user EQ user_id ? 'selected' : ''#

    which is the same as

    <cfif structKeyExists(form,"user") AND form.user EQ user_id>
      selected
    </cfif>

     

    Peru Bob
    Community Expert
    Community Expert
    March 25, 2021

    I've moved this from the Using the Community forum (which is the forum for issues using the forums) to the ColdFusion forum so that proper help can be offered.