According to MSDN, “IsNumeric returns a Boolean value indicating whether an expression can be evaluated as a number”, and (Numerical Datatype).TryParse converts the string representation of a number to its relevant numerical equivalent. A return Boolean value indicates whether the conversion succeeded or failed.
I have seen several cases where the developers were using TryParse or isNumeric only for validation, and they were not using a numeric variable at all; however, this could still cause functional and/or security issues in certain cases.
What is wrong with TryParse or IsNumeric then?!
There is nothing wrong with these functions if they are used correctly. In fact, these functions should not be used for validation only; they tell us if we can convert a string to its numerical format, and therefore, we can use a proper numerical variable instead of the string.
However, (numerical Datatype).TryParse is more useful than IsNumeric and can create the numerical equivalent as an output which can be used safely afterwards; it can also accept the permitted format(s) and the required culture format.
When can it go wrong?
From TryParse or IsNumeric point of view, a string can still be numeric even if it has some control characters or it follows a specific format as it can still be converted to a number. Therefore, the original string can be completely different in length and format from its equivalent numeric value. Now, if you use the original string when the results of these functions are true, we may have issues based on the destination system that uses them and trusts your validation. In real examples, I have seen a denial of service because of having a Null character in a serialized XML in the memory, or a denial of service because of sending a long string to a C++ component which did not have any validation and trusted the provided data.
The following table shows several test cases that can be combined as well (I have used URLEncoded values for the space and control characters):
|001.0000||True||True||1||decimal symbol based on the regional settings of the server|
|$10||True||False||10||Currency symbol based on the regional settings of the server.|
|1,,2,,,3,,||True||True||123||Digit grouping symbol based on the regional settings of the server. Can be created by HPP too.|
|-10.0||True||True||-10||Negative symbol based on the regional settings of the server. It could be a positive sign.|
|(10)||True||False||-10||Negative symbol based on the regional settings of the server.|
|10-||True||False||-10||Negative symbol based on the regional settings of the server. It could be a positive sign.|
|1e2||True||True||100||String length can be less than the number’s length|
|%20%091||True||True||1||Space characters (09-0D and 20)|
|1%20%00%00||True||True||1||Space characters (09-0D and 20) followed by Null Character(s)|
|%26hff||True||False||255||&h and &o can be used in VBScript to represent a number in Hex or Octal.|
You can try IsNumeric function by using the following link:
Source Code: http://sdl.me/NumericTest/IsNumericTester.ashx.vb.txt
You can try Double.TryParse function by using the following link:
Source code: http://sdl.me/NumericTest/DoubleTryParseTester.ashx.cs.txt
In .Net, (Numeric Data Type).TryParse automatically updates the relevant numeric variable for you that can be used later; it also accepts permitted format(s) and the required culture format of the input which is highly recommended to be used when you are looking for a specific format.
Source code: http://sdl.me/NumericTest/SafeDoubleTryParseTester.ashx.cs.txt
However, if you are a fan of using IsNumeric in VB, just make sure that you create a relevant numeric variable based on the input and convert the string to a number.
Another solution that may reduce the performance is validation by using a Regular Expression to check the numeric inputs in string. This method can be more useful if you are using different technologies (for example Java and .Net) at the same time to maintain consistency.