Today's muse is Henry, with this Twitter status message:
#coldfusion sandbox security requires FileRead() because some code uses "new Query()" due to base.cfc. That's a pretty bad design, no?
— Henry Ho (@henrylearn2rock) July 14, 2014
My reaction to that was along the lines of "WTF?", so as soon as I got into the office I had a look in base.cfc ([ColdFusion dir]\cfusion\CustomTags\com\adobe\coldfusion\base.cfc), and low-and behold, I see this code:
private string function getSupportedTagAttributes(string tagName)
{
//store all service tag attributes in Server scope for faster access.
if(not isdefined("server.coldfusion.serviceTagAttributes.#tagName#"))
{
lock scope="server" timeout="30" throwontimeout="yes" type="exclusive"
{
if(not isdefined("server.coldfusion.serviceTagAttributes.#tagName#"))
{
var webinf = getPageContext().getServletContext().getRealPath("/WEB-INF");
var sep = server.os.name contains "windows"? "\" : "/";
var cftldpath = webinf & sep & "cftags" & sep & "META-INF" & sep & "taglib.cftld";
var xpath = "/taglib/tag[name='#lcase(Right(tagName,len(tagName)-2))#']/attribute/name";
var cftagsXml = XmlParse(FileRead(cftldpath));
var tagAttributes = xmlsearch(cftagsXml,xpath);
var attributeslist = "";
var i = 0;
for(i=1;i lte arraylen(tagAttributes); i++)
{
attributeslist = listappend(attributeslist,trim(tagAttributes[i].xmltext));
}
server.coldfusion.serviceTagAttributes[tagName] = listsort(attributeslist,"textnocase","ASC");
}
}
}
//use a local variable for faster access
lock scope="server" timeout="30" throwontimeout="yes" type="readonly"
{
var attributeslist = server.coldfusion.serviceTagAttributes[tagName];
}
return attributeslist;
}
getSupportedTagAttributes()
is called in the pseudo-constructor of query.cfc (and all the other CFCs in that directory as well).So the first time one uses one of these CFCs during the life of the server instance, it locks the server scope, reads-in the tag definition file, XML-parses it, finds the attributes for the tag version of the functionality, and stores that stuff in the server scope. At least it's only doing it the once.
But that's a really shit way of going about things. Mindnumbingly shit.
Query.cfc is specifically for emulating
<cfquery>
. It has <cfquery>
-specific values throughout its code. So why the hell does it need to make a generic all to the filesystem, locking the entire server along the way, simply to read in which attributes to support? It's already got reference to most of these hard-coded immediately above in the same pseudo-constructor:component extends="base"
{
property string name;
property numeric blockfactor;
property string cachedafter;
property string cachedwithin;
property string dataSource;
property string dbtype;
property boolean debug;
property numeric maxRows;
property string password;
property string result;
property numeric timeout;
property string username;
property string sql;
property string fetchclientinfo;
property struct clientinfo;
//array to store cfqueryparams
variables.parameters = [];
//service tag to invoke
variables.tagName = "CFQUERY";
//list of valid cfquery tag attributes
variables.tagAttributes = getSupportedTagAttributes(getTagName());
So just hard code the rest of them! especially if "store all service tag attributes in Server scope for faster access". You're only having to worry about that because of your shit-house approach to getting the data you need anyhow.I had previously noted how abjectly shite the code in these CFCs was, but this takes the cake.
Whoever wrote this code should not be allowed to write code ever again. And I hate to think what the quality of the Java code is under the hood of ColdFusion, if this is an example of how they implement stuff. Scary.
--
Adam