I've just experienced a behaviour that defies any logic and could potentially lead to serious issues and was wondering if it was a bug or if the behaviour was itended and what are the best practices to circumvent the issue? If it's a bug, is there a patch?
Here's the two wierd behaviours that when put together are a threat to any system's data integrity.
int('1 2')
->41276
isValid('numeric', '1 2')
->true
Why? Well let's see...
<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')>
Here, the type="numeric"
arguments validation (which perhaps is based on the same algorithm as isValid
?) doesn't throw with '1 2'
. Even worse, cfqueryparam cfsqltype="cf_sql_integer"
seems to be using int
to convert the value which will end up being 41276
.
In other words, deleteSomething('1 2')
will delete the entity with id 41276
instead of throwing an exception since the value 1 2
is obviously not numeric.
Now, the only fix I thought of is to perform additionnal argument validation using isValid('integer', ...
or a regular expression, but that's a real pain and besides, I never understood why they haven't implemented type="integer"
?
Obviously, I also always made the false assumption that cfqueryparam type="cf_sql_integer"
would validate that the value passed is a valid integer.
EDIT:
It seems that even isvalid('integer', ...
is also not reliable as we can see in
Why isvalid("integer","1,5") = YES?
EDIT2:
I know that I could add additionnal arguments validation for every expected integer argument in every function, however that would require to fix a huge code base in my case and it's also very error-prone. It also makes the built-in argument validation completely useless in this case.
I would rather prefer a solution where I could create and apply an unofficial patch. Is that a realistic option? If so I would like to be pointed out in the right direction.
EDIT3: It doesn't solves all the problems, but CF11 added support for a strictNumberValidation application level configuration.
"Starting from ColdFusion 11, this function evaluates on a more strict basis. Setting this value to false makes the isValid function to behave in the older way. This setting effects cfargument, cfparam and cfform tags wherever integer & numeric validation is used. Based on this setting, the validation reflects in those tags as well."
This is a variation on that theme from the other question. See this code (or run it on cflive.net):
<cfscript>
s = "1 2";
i = int(s);
v = isValid("numeric", s);
d = createOdbcDate(s);
writeDump([s,i,v,d]);
</cfscript>
s
converts to 41276
when calling int()
, and when using it as an input for createOdbcDate()
, we get:
January, 02 2013 00:00:00 +0000
So "1 2"
is being interpreted as "m d"
, with an implied year of the current year.
Which is utterly stupid. But there you go.
You can use regular expressions to find out if there are any non numeric characters in a given form field:
reFind( "[^\d-]", "1 2")
That will match any character that is not a number, not a -
If you want to check only positive numbers, you can use
reFind( "[^\d]", "1 2")
If this returns true
, you do not have an integer.
来源:https://stackoverflow.com/questions/19140219/coldfusion-9-int-and-type-numeric-nasty-bug