CS.ABV.EXCEPT

IndexOutOfRange exception while attempting to use an out-of-bounds array index

Unlike C and C++, the C# language has built-in protection against out-of-boundary reads and writes for arrays and containers allocated on a managed heap. With the protection in place, attempts to read or write the out-of-boundary memory will not succeed; however, using an invalid access index will result in an IndexOutOfRangeException thrown by the array access operator.

The CS.ABV.EXCEPT checker inspects index access operations and flags situations where index values can be invalid.

Vulnerability and risk

While a buffer overrun is not possible for arrays allocated on a managed heap, an unhandled or incorrectly handled exception can result in program termination or alter control flow in unexpected ways. Even when the IndexOutOfRange exception is handled properly, the possibility of an index value being outside of the array bounds is a strong indication of a logical error that can result in incorrect program results.

Vulnerable code example 1

Copy
   namespace n {
       class C
       {
           void foo()
           {
               int[] A = new int[5];
               int ind = 4;
               ++ind;
               A[ind] = 10;            // CS.ABV.EXCEPT
          }
      }
  }

In this basic example, an array ‘A’ of size 5 is allocated, and index ‘ind’, that is equal to 5 at the access site, is used to reference the array element. If this code executed, an IndexOutRangeException would be thrown at runtime. Klocwork reports this problem as a CS.ABV.EXCEPT defect.

Fixed code example 1

Copy
   namespace n {
       class C
       {
           void foo()
           {
               int[] A = new int[6];
               int ind = 4;
               ++ind;
               A[ind] = 10;
          }
      }
  }

The problem can be fixed by verifying the correctness of the array access logic. In the above fixed example, the array size is adjusted to ensure the access index is within the array bounds.

Vulnerable code example 2

Copy
   namespace n
   {
       class C
       {
           static void Main(string[] args)
           {
               int[] E = { 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10 };
   
               int ind1 = 5;
              for (int i = 0; i < args.Length; i++)
              {
                  ++ind1;
                  if (i == 10)
                  {
                      break;
                  }
              }
  
              E[ind1] = 0;            // CS.ABV.EXCEPT
          }
      }
  }

In this example, ‘E’ is initialized with an implicitly typed array of size 10. Depending on the length of ‘args’ passed to the ‘Main’ value of the access index, there can be as many as 11 possible iterations in the loop that can result in values of ‘ind1’ being anywhere in range [5;16]. Klocwork reports this problem as a CS.ABV.EXCEPT defect, indicating the part of the possible access index range that will result in the IndexOutRangeException being thrown.

Fixed code example 2

Similarly to example 1, the problem can be addressed by the careful evaluation of possible index values and array sizes.

Copy
   namespace n
   {
       class C
       {
           static void Main(string[] args)
           {
               int[] E = { 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10 };
  
               int ind1 = 5;
              for (int i = 0; i < args.Length; i++)
              {
                  ++ind1;
                  if (i == 3)    // Fixed here in this example.
                  {
                      break;
                  }
              }
  
              E[ind1] = 0;
          }
      }
  }

In this fixed example, values of ‘ind1’ are guaranteed to be within the array bounds.

Limitations

In Klocwork 2021.3, the CS.ABV.EXCEPT checker only supports the intra-procedural analysis of array accesses for arrays of value-type elements.

Related checkers

Security training

Application security training materials provided by Secure Code Warrior.