public void Test1() { int len1 = this.arr.Length; int len2 = len1 + 1; // OK for (int i = 0; i < len2 - 1; i++) { ContainerLengthOffByOne.Fun(this.arr[i]); } }
public void Test6() { int len = this.arr.Length - 2; int len1 = len + 3; int len2 = len1 - 1; // Not OK, off by one // The test shows that more complex expressions are treated correctly for (int i = 0; i < len2; i++) { ContainerLengthOffByOne.Fun(this.arr[i + 1]); } }
public void Test7() { int[] arrInit = { 1, 2, 3 }; int len = (arrInit.Length * 2 + 2) / 2 * 2; int len1 = len / 2 - 3 + 4; // Not OK, len1 == this.arrInit + 1 // This test shows that array initializer's length // are used in bounds for (int i = 0; i < len1; i++) { ContainerLengthOffByOne.Fun(arrInit[i]); } }
public void Test4() { int len1 = this.arr.Length; int len2 = len1 + 1; int len3 = len2 - 1; int len4 = len3 + 2; int len5 = len4 - 1; // Not OK, len5 is off by one. for (int i = 0; i < len5; i++) { ContainerLengthOffByOne.Fun(this.arr[i]); } }
public void Test2() { int len1 = this.arr.Length; int len2; if (len1 % 2 == 0) { len2 = len1 + 1; } else { len2 = len1; } // Not OK, PHI node where the upper bound // exceeds the size of the array. for (int i = 0; i < len2; i++) { ContainerLengthOffByOne.Fun(this.arr[i]); } }
public void Test3() { int len1 = this.arr.Length; int len2 = len1 - 1; int len3; if (len2 % 2 == 0) { len3 = len2 + 1; } else { len3 = len2; } // OK, PHI node has bounds that ensure // we don't get an off by one error. for (int i = 0; i < len3; i++) { ContainerLengthOffByOne.Fun(this.arr[i]); } }