这是一个关于cfscript中是否存在ColdFusion Bug的问题。

3

这是一个有效的查询,可以从用户表中返回用单引号括起来的电子邮件。

SELECT  '''' +email + '''' as email
FROM    users
where fname = @fname

当我尝试在cfscript(cf9)查询中这样做时:

var q = new Query(datasource="warewithal");
q.setSQL("SELECT  '''' +email + '''' as email
                FROM users where firstName= :firstName ");
q.addParam(name="firstName", value=trim(firstName), cfsqltype="cf_sql_varchar");

我最终得到的是什么。
Email
+email+

当我预期并在分析器中运行查询时获得的结果是:

Email
'bozo@clowns.com'

cfscript 正在执行 perserveSingleQuote 操作,不允许我将单引号添加到输出中。

这是一个 bug 吗?还是我做错了什么?


2
你试过只用两个单引号而不是四个吗?三个、五个或六个呢? - Nathan Strutz
你使用的是哪种数据库类型?(在与查询相关的问题的标签中包含这一信息总是很有用的)。 - Leigh
1
虽然这与在 Query.cfc 中使用 preserveSingleQuotes 有关,但我在针对 SQL Server 进行测试时得到了不同的结果(数据库语法错误)。因此,目前尚不清楚这是否是一个 bug,或者如果是 bug 的话,它是否严格属于 CF 的 bug。不确定您为什么需要这样做,但作为解决方法,您可以在演示层中使用 CF 代码(更典型的方法)添加它,或者可能使用数据库的字符串函数来生成单引号。例如,在 SQL Server 中:SELECT char(39) + email + char(39) AS Email ... - Leigh
3
我正在尝试理解为什么你需要将结果用单引号括起来。当你需要输出时,直接在电子邮件地址周围加上单引号可能更容易一些,不是吗? - Scott Stroz
你也可以尝试使用数据库管理系统内置的连接函数,例如SQL Server中的concat()。 - genericHCU
2个回答

5
回答你标题中的问题:不,这不是CFScript中的错误。你展示的内容根本与CFScript无关。
然而,回答你实际想问的问题:是的,你发现了Query.cfc中的一个bug。
以下是一些演示该错误的代码(并且演示它与CFScript无关,与Query.cfc有关)。
以下代码可以正常工作:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
    SELECT  '''' + email + '''' as email
    FROM    users
    WHERE   firstName = '#firstName#'   
")>
<cfset emailAddresses = query.execute().getResult()> 
<cfdump var="#emailAddresses#">

请注意,我已经将过滤器值硬编码到SQL字符串中了。有点讨厌。
这段代码出现了错误:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
    SELECT  '''' + email + '''' as email
    FROM    users
    WHERE   firstName = :firstname  
")>
<cfset query.addParam(name="firstname", value=firstName, cfsqltype="CF_SQL_VARCHAR")>
<cfset emailAddresses = query.execute().getResult()> 
<cfdump var="#emailAddresses#">

我的错误信息是: [Macromedia][SQLServer JDBC Driver][SQLServer]对象或列名称缺失或为空。对于SELECT INTO语句,请验证每个列都有名称。对于其他语句,查找空别名。别名定义为“”或[]是不允许的。将别名更改为有效名称。 FYI:CF传递给数据库的SQL是:
SELECT  '' '' + email + '' '' as email FROM users WHERE firstName = (param 1)

为了证明这是由于ColdFusion错误处理单引号导致的,可以使用以下方法:
<cfset query = new Query(datasource="scratch_mssql")>
<cfset query.setSql("
    SELECT  email as email
    FROM    users
    WHERE   firstName = :firstname  
")>
<cfset query.addParam(name="firstname", value=firstName, cfsqltype="CF_SQL_VARCHAR")>
<cfset emailAddresses = query.execute().getResult()> 
<cfdump var="#emailAddresses#">

如果我是你,我会为此提出一个漏洞报告。注意:CF9.0.2和CF10.0.7上也是一样的。

但是同样地,如果我是你,我不会在那里放这些引号。除非有非常好的理由,在处理数据时不要加引号,而是在显示时再加。我猜它们是为了显示目的而放置的?


@Travis:我已经更新了文本,包括SQL语句。在CF9和10上都是相同的。 - Adam Cameron
@AdamCameron - 听起来Railo可能使用类似的逻辑。我猜两个引擎都没有考虑到这种情况,即用单引号包围列/值。Railo的SQL是什么样子的(我现在无法测试)? - Leigh
@Leigh。这是一样的,只是分散在40多行上(它们似乎有一些空格控制问题...) - Adam Cameron
感谢大家的所有建议。我们最终采用了不同的方式添加单引号。正如几位人士建议的那样,总有一种解决方法。不幸的是,由于 SQL 语法正确,我们浪费了一些时间来弄清楚我们做错了什么。但这就是游戏的一部分。@Adam 感谢您注册此错误。 - Lance
@Lance:是的,我建议你提出这个漏洞。我只是给了你一个URL来做到这一点。如果你在这里发布漏洞参考,我会投票支持它。 - Adam Cameron
显示剩余7条评论

0
说实话,我也遇到了这个问题。看起来解决方法很简单,只需要修改你的Query.cfc对象(/[YOUR-CF-INSTALL]/CustomTags/com/adobe/coldfusion/Query.cfc)即可。在replaceDelimsWithMarkers()函数中,更新这一行代码(对我来说是第341行)。
newSql = newSql & SINGLEQUOTE & sqlArray[i] & SINGLEQUOTE & " ";

通过删除末尾的引号空格,使其变为:
newSql = newSql & SINGLEQUOTE & sqlArray[i] & SINGLEQUOTE & "";

然后它运行得很好。我在查找用户时需要找到姓氏为“O'Neill”的用户。无论我做什么,我都会得到“O''Neill”,正如您所述失败。

您能想到任何情况下这种更改/修复会产生负面影响吗?我一时想不出来,但现在我们将复制query.cfc文件,将其重命名并仅在我们需要运行查询且怀疑可能使用额外的撇号时使用它作为自定义标记。唯一的区别将是这个小改变。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接