【问题标题】:ColdFusion 9: int and type="numeric" nasty bug?ColdFusion 9:int 和 type="numeric" 讨厌的错误?
【发布时间】:2013-10-02 15:05:30
【问题描述】:

我刚刚经历了一种违反任何逻辑并可能导致严重问题的行为,我想知道 这是否是一个错误,或者该行为是否已解决,以及规避该问题的最佳做法是什么?如果是bug,有补丁吗?

以下是两种奇怪的行为,它们放在一起会对任何系统的数据完整性构成威胁。

  1. int('1 2') -> 41276
  2. isValid('numeric', '1 2') -> true

为什么?好吧,让我们看看...

<cffunction name="deleteSomething" access="public" returntype="void">
    <cfargument name="somethingId" type="numeric" required="yes">

    <cfquery datasource="#dsn()#">
        DELETE
        FROM Something
        WHERE id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.somethingId#">;   
    </cfquery>

</cffunction>


<cfset deleteSomething('1 2')>

这里,type="numeric" 参数验证(可能基于与isValid 相同的算法?)不会与'1 2' 一起抛出。更糟糕的是,cfqueryparam cfsqltype="cf_sql_integer" 似乎正在使用int 来转换最终将成为41276 的值。

换句话说,deleteSomething('1 2') 将删除 ID 为 41276 的实体,而不是抛出异常,因为值 1 2 显然不是数字。

现在,我想到的唯一解决方法是使用 isValid('integer', ... 或正则表达式执行附加参数验证,但这真的很痛苦,此外,我不明白他们为什么没有实现 type="integer"

显然,我也总是错误地假设cfqueryparam type="cf_sql_integer" 会验证传递的值是一个有效的整数。

编辑:

似乎即使isvalid('integer', ...也不可靠,正如我们在
Why isvalid("integer","1,5") = YES?中看到的那样

编辑2:

我知道我可以为每个函数中的每个预期整数参数添加额外的参数验证,但是在我的情况下这需要修复一个巨大的代码库,而且它也很容易出错。在这种情况下,它还使内置参数验证完全无用。

我更喜欢可以创建和应用非官方补丁的解决方案。这是一个现实的选择吗?如果是这样,我想指出正确的方向。

EDIT3:它并没有解决所有问题,但 CF11 增加了对 strictNumberValidation 应用程序级别配置的支持。

"从 ColdFusion 11 开始,此函数在更严格的 基础。将此值设置为 false 会使 isValid 函数 以旧的方式行事。此设置影响 cfargument、cfparam 和 使用整数和数字验证的 cfform 标记。基于 此设置,验证也反映在这些标签中。”

【问题讨论】:

  • 重复的问题:stackoverflow.com/questions/11535979/why-isvalidinteger-1-5-yes 似乎 adobe 没有解决这个问题。
  • @Jarede,感谢您的参考。但是我相信我的问题突出了一些异常情况,并且不是重复的。
  • 如果您查看相关的 SO 问题,它几乎可以回答您提出的所有问题。有关详细信息,请参阅@Mike Causer 的答案。
  • 我发现在 CF8、9 和 10 中,对 ColdFusion 变量名的 isValid("variablename") 测试也会忽略空格。isValid("variablename", "abc") 评估为“有效”ColdFusion变量名,即使有前导和尾随空格。
  • isDate() 函数也好不了多少。它为“4 月 31 日”返回 true。

标签: coldfusion int numeric cfqueryparam


【解决方案1】:

这是另一个问题的主题变体。查看此代码(或在cflive.net 上运行):

<cfscript>
s = "1 2";
i = int(s);
v = isValid("numeric", s);
d = createOdbcDate(s);
writeDump([s,i,v,d]);
</cfscript>

s 在调用int() 时转换为41276,当将其用作createOdbcDate() 的输入时,我们得到:

January, 02 2013 00:00:00 +0000

所以"1 2" 被解释为"m d",隐含的是当年的年份。

这完全是愚蠢的。但是你去吧。

【讨论】:

  • 有什么方法可以创建和应用非官方补丁吗?在这种情况下,这种行为使内置参数验证完全无用。
  • @JamesMohler,并非如此。问题是必须修复极其庞大的代码库和不必要的开销,这是通过对每个预期的整数参数执行附加类型检查所暗示的。我肯定更愿意从根本上解决问题。
  • @AdamCameron 你能看看我的第一条评论吗?
  • 不,我不知道“非正式地”修补 ColdFusion。至于你如何调整你的方法以减轻它,我们必须了解你是如何以你现在的方式使用这样的字符串(这似乎有点奇怪,TBH)。也许这里有一个新问题,有更多细节?
  • @AdamCameron 我没有使用字符串,示例的 API 旨在获取数值。但是,由于该错误,如果开发人员犯了错误并传递了类似'1 2' 的内容,CF 将不会抱怨,这将很难调试。因此,这使得内置参数验证对于这种情况毫无用处。
【解决方案2】:

您可以使用正则表达式来找出给定表单字段中是否有任何非数字字符:

reFind( "[^\d-]", "1 2")

这将匹配任何不是数字的字符,而不是-

如果你只想检查正数,你可以使用

reFind( "[^\d]", "1 2")    

如果返回true,则您没有整数。

【讨论】:

  • 谢谢,但我已经在问题中说明了该解决方案。
  • --0---0-- 不是数字;检查输入是否是带有正则表达式的有符号整数最好使用 NOT refind( "^-?\d+$" , input ) ... 对于第二个,\D[^\d] 的快捷方式
  • 好点。这将让我学会不要快速编写正则表达式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多