[corlib] Add more convert checks
authorMarek Safar <marek.safar@gmail.com>
Mon, 19 Jan 2015 18:49:58 +0000 (19:49 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 19 Jan 2015 18:50:36 +0000 (19:50 +0100)
mcs/class/corlib/ReferenceSources/ParseNumbers.cs
mcs/class/corlib/System/Decimal.cs
mcs/class/corlib/Test/System/ConvertTest.cs
mcs/class/corlib/Test/System/DecimalTest.cs

index 9711c90702cddb8fd52156517730ce678d28f5ea..7f70cd565cd89af62c87d796b2efcfaf7406b415 100644 (file)
@@ -51,7 +51,7 @@ namespace System {
                                return 0;
 
                        int chars = 0;
-                       int result = 0;
+                       uint result = 0;
                        int digitValue;
 
                        int i = 0; 
@@ -81,6 +81,15 @@ namespace System {
                                i += 2;
                        }
 
+                       uint max_value;
+                       if ((flags & TreatAsI1) != 0) {
+                               max_value = Byte.MaxValue;
+                       } else if ((flags & TreatAsI2) != 0) {
+                               max_value = UInt16.MaxValue;
+                       } else {
+                               max_value = UInt32.MaxValue;
+                       }
+
                        while (i < len) {
                                char c = value [i++];
                                if (Char.IsNumber (c)) {
@@ -103,14 +112,25 @@ namespace System {
                                        throw new FormatException ("Could not find any parsable digits.");
                                }
 
-                               result = fromBase * result + digitValue;
+                               if ((flags & TreatAsUnsigned) != 0) {
+                                       result = (uint) fromBase * result + (uint) digitValue;
+                                       if (result > max_value)
+                                               throw new OverflowException ();
+                               } else {
+                                       var res = (uint) fromBase * result + (uint) digitValue;
+                                       if (res < result || res > max_value)
+                                               throw new OverflowException ();
+                                       
+                                       result = res;
+                               }
+
                                chars++;
                        }
 
                        if (chars == 0)
                                throw new FormatException ("Could not find any parsable digits.");
 
-                       return negative ? -result : result;
+                       return negative ? -(int)result : (int)result;
                }        
 
                public static string LongToString (long value, int toBase, int width, char paddingChar, int flags)
index b98094c22083eef41193b72defd68078999a83d9..66bbd1ed871f00496b2c8c1968259b6bdbb2b147 100644 (file)
@@ -559,6 +559,9 @@ namespace System
                                throw new ArgumentOutOfRangeException ("decimals", "[0,28]");
                        }
 
+                       if (mode == MidpointRounding.ToEven && decimals == 0)
+                               return Round (d);
+
                        bool negative = d.IsNegative ();
                        if (negative)
                                d.flags ^= SIGN_FLAG;
index bc02ab927a6af04592bdaefe279cd62d1508e1b1..caee51fd3cbd346522ff4c8bbd5cf26ee8a2fe8c 100644 (file)
@@ -64,6 +64,7 @@ namespace MonoTests.System {
                        ci.NumberFormat.NumberDecimalDigits = 3;
                }
 
+               [Test]
                public void TestChangeType() {
                        int iTest = 1;
                        try {
@@ -93,7 +94,11 @@ namespace MonoTests.System {
                                iTest++;
                                Assert.AreEqual ((float)1234, Convert.ChangeType(tryInt16, typeof(float), ci), "#A12");
                                iTest++;
-                               Assert.AreEqual (null, Convert.ChangeType(null, null, ci), "#A13");
+                               try {
+                                       Assert.AreEqual (null, Convert.ChangeType(null, null, ci), "#A13");
+                                       Assert.Fail ("#F13");
+                               } catch (ArgumentNullException) {
+                               }
 
                                iTest++;
                                Assert.AreEqual ((decimal)0, Convert.ChangeType(tryByte, TypeCode.Decimal, ci), "#A14");
@@ -202,6 +207,7 @@ namespace MonoTests.System {
 
                }               
 
+               [Test]
                public void TestGetTypeCode() {
                        int marker = 1;
                        try {
@@ -241,6 +247,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestIsDBNull() {
                        Assert.AreEqual (false, Convert.IsDBNull(tryInt32), "#C01");
                        Assert.AreEqual (true, Convert.IsDBNull(Convert.DBNull), "#C02");
@@ -249,6 +256,7 @@ namespace MonoTests.System {
                        Assert.AreEqual (false, Convert.IsDBNull(tryFloat), "#C05");
                }
                
+               [Test]
                public void TestToBoolean() {
                        tryObj = (object)tryDbl;
                        
@@ -304,6 +312,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToByte() {
                        
                        Assert.AreEqual ((byte)1, Convert.ToByte(boolTrue), "#E01");
@@ -464,6 +473,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToChar(){
                        tryByte = 58;
                        Assert.AreEqual (':', Convert.ToChar(tryByte), "#F01");
@@ -631,6 +641,7 @@ namespace MonoTests.System {
                        Convert.ToDateTime("20002-25-01");
                } */
 
+               [Test]
                public void TestToDateTime() {
                        string dateString = "01/01/2002";
                        int iTest = 1;
@@ -857,6 +868,7 @@ namespace MonoTests.System {
 
                }
 
+               [Test]
                public void TestToDecimal() {
                        Assert.AreEqual ((decimal)1, Convert.ToDecimal(boolTrue), "#H01");
                        Assert.AreEqual ((decimal)0, Convert.ToDecimal(boolFalse), "#H02");
@@ -964,6 +976,7 @@ namespace MonoTests.System {
                        }
                }
                
+               [Test]
                public void TestToDouble() {
                        int iTest = 1;
                        try {
@@ -1078,6 +1091,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToInt16() {
                        Assert.AreEqual ((short)0, Convert.ToInt16(boolFalse), "#J01");
                        Assert.AreEqual ((short)1, Convert.ToInt16(boolTrue), "#J02");
@@ -1284,6 +1298,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToInt32() {
                        long tryMax = long.MaxValue;
                        long tryMin = long.MinValue;
@@ -1461,6 +1476,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToInt64() {
                        decimal longMax = long.MaxValue;
                        longMax += 1000000;
@@ -1600,6 +1616,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToSByte() {
                        int iTest = 1;
                        try {
@@ -1853,6 +1870,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToSingle() {
                        int iTest = 1;
                        try {
@@ -1954,6 +1972,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToString() {
                        
                        tryByte = 123;
@@ -2031,6 +2050,7 @@ namespace MonoTests.System {
                        }                       
                }
 
+               [Test]
                public void TestToUInt16() {
                        Assert.AreEqual ((ushort)0, Convert.ToUInt16(boolFalse), "#P01");
                        Assert.AreEqual ((ushort)1, Convert.ToUInt16(boolTrue), "#P02");
@@ -2239,6 +2259,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestSignedToInt() {
                  //  String cannot contain a minus sign if the base is not 10.
                  // But can if it is ten, and + is allowed everywhere.
@@ -2270,6 +2291,7 @@ namespace MonoTests.System {
 
                }
        
+               [Test]
                public void TestToUInt32() {
                        Assert.AreEqual ((uint)1, Convert.ToUInt32(boolTrue), "#Q01");
                        Assert.AreEqual ((uint)0, Convert.ToUInt32(boolFalse), "#Q02");
@@ -2461,6 +2483,7 @@ namespace MonoTests.System {
                        }
                }
 
+               [Test]
                public void TestToUInt64() 
                {
                        int iTest = 1;
@@ -2714,6 +2737,7 @@ namespace MonoTests.System {
                                Assert.AreEqual (bb [i], b2 [i], "#0" + (i + 2));
                }
                
+               [Test]
                public void TestToBase64CharArray ()
                {
                        byte[] byteArr = {33, 127, 255, 109, 170, 54};
@@ -2808,6 +2832,7 @@ namespace MonoTests.System {
                        Convert.ToBase64CharArray (byteArr, 0, byteArr.Length, result, Int32.MaxValue);
                }
 
+               [Test]
                public void TestToBase64String() {
                        byte[] byteArr = {33, 127, 255, 109, 170, 54};
                        string expectedStr = "IX//bao2";
@@ -3442,6 +3467,28 @@ namespace MonoTests.System {
                        Assert.AreEqual (Int64.MinValue, Convert.ToInt64 ("1000000000000000000000000000000000000000000000000000000000000000", 2), "1000000000000000000000000000000000000000000000000000000000000000,2");
                }
 
+               [Test]
+               public void MoreOverflows ()
+               {
+                       try {
+                               Convert.ToInt16 ("ffff7fff", 16);
+                               Assert.Fail ("#1");
+                       } catch (OverflowException) {
+                       }
+
+                       try {
+                               Convert.ToSByte ("ffff7fff", 16);
+                               Assert.Fail ("#2");
+                       } catch (OverflowException) {
+                       }
+
+                       try {
+                               Convert.ToUInt32 ("4294967298", 10);
+                               Assert.Fail ("#3");
+                       } catch (OverflowException) {
+                       }
+               }
+
                // signed types
 
                [Test]
index dc02ab58663032c6011fa5917b6dedc4b70b17de..2758c3333960543af6b8943aab27744ee8e1635b 100644 (file)
@@ -1563,6 +1563,7 @@ namespace MonoTests.System
                        Assert.AreEqual ("3", Math.Round (3M, 5).ToString (CultureInfo.InvariantCulture), "#1");
                        Assert.AreEqual ("3.01", Math.Round (3.01M, 5).ToString (CultureInfo.InvariantCulture), "#2");
                        Assert.AreEqual ("-3.01", Math.Round (-3.01M, 5).ToString (CultureInfo.InvariantCulture), "#3");
+                       Assert.AreEqual ("128", Math.Round (127.5M, 0).ToString (CultureInfo.InvariantCulture), "#4");
                }
        }
 }