[Mono-bugs] [Bug 47707][Cri] New - Missing bounds checking in Array.IList.this[]
bugzilla-daemon@bugzilla.ximian.com
bugzilla-daemon@bugzilla.ximian.com
Mon, 18 Aug 2003 13:04:02 -0400 (EDT)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by lb@lb.ods.org.
http://bugzilla.ximian.com/show_bug.cgi?id=47707
--- shadow/47707 2003-08-18 13:04:02.000000000 -0400
+++ shadow/47707.tmp.31804 2003-08-18 13:04:02.000000000 -0400
@@ -0,0 +1,107 @@
+Bug#: 47707
+Product: Mono/Class Libraries
+Version: unspecified
+OS: All
+OS Details:
+Status: NEW
+Resolution:
+Severity:
+Priority: Critical
+Component: CORLIB
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: lb@lb.ods.org
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: Missing bounds checking in Array.IList.this[]
+
+Description of Problem:
+Array.GetValueImpl and Array.SetValueImpl are implemented in unmanaged code
+without bounds checking.
+
+This is sensible since it is faster and allows managed code to freely
+handle out-of-bounds cases according the specification; however it means
+that managed code MUST ensure that the parameter it passes to the two
+functions is within bounds.
+
+
+Unfortunately, there is code that doesn't bother to do so:
+
+// IList interface
+object IList.this [int index] {
+ get {
+ return GetValueImpl (index);
+ }
+ set {
+ SetValueImpl (value, index);
+ }
+}
+[This seems the only such code, but I don't make any guarantee]
+
+
+Test cases:
+ public volatile object volatile_obj = null;
+
+#if NET_1_1
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void TestIList_Item_GetLowerBound()
+ {
+ object[] a = new object[16];
+ IList l = (IList)a;
+ volatile_obj = l[-1];
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void TestIList_Item_GetUpperBound()
+ {
+ object[] a = new object[16];
+ IList l = (IList)a;
+ volatile_obj = l[16];
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void TestIList_Item_SetLowerBound()
+ {
+ object[] a = new object[16];
+ IList l = (IList)a;
+ l[-1] = volatile_obj;
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void TestIList_Item_SetUpperBound()
+ {
+ object[] a = new object[16];
+ IList l = (IList)a;
+ l[16] = volatile_obj;
+ }
+#endif
+
+Steps to reproduce the problem:
+1. Run the test case or equivalent code
+
+Actual Results:
+If an access violation happens, the following:
+
+Unhandled Exception: System.NullReferenceException: A null value was found
+where an object instance was required
+in (unmanaged) /usr/lib/libmono.so.0(mono_value_box+0xde) [0x4008e7aa]
+in (unmanaged) /usr/lib/libmono.so.0 [0x400905ac]
+in <0x00015> 00 System.Array:System.Collections.IList.get_Item (int)
+in <0x00057> 00 .App:Main ()
+
+Otherwise, it reads/writes to an arbitrary attacker-selectable memory
+address (on 64-bit systems some addresses may not be reachable), which is a
+complete security bypass and a specification violation.
+
+
+Patch:
+Should be attached.
+
+The idea of the unchecked unsigned casts is to do both lower and upper
+bounds checking in a single operation since negative values get mapped to
+0x80000000-0xffffffff.