Webinar: Evaluation - 05.12
The array index out of bounds error is a special case of the buffer overflow error. It occurs when the index used to access array items exceeds a valid value. In this case, an array element is accessed outside the array boundaries, which is undefined behavior. It's happens because there is no strict control over array overruns in C and C++ programming languages. Whether there will be checks or not depends on the tools used and their implementation.
The array index out of bounds error can be found using the static or dynamic code analyzers. Checking for these errors is advisable as it may take much time before these errors reveal themselves. The program operation will depend on the compiler version, operating system, the affected data, etc.
Let's take a look at the error on the examples found in the code of real open-source projects using the PVS-Studio static analyzer.
The Dump project (Dynamic Universal Music Bibliotheque) code:
struct IT_SAMPLE
{
....
unsigned char filename[14];
....
};
static int it_riff_dsmf_process_sample(
IT_SAMPLE * sample, const unsigned char * data, int len)
{
int flags;
memcpy( sample->filename, data, 13 );
sample->filename[ 14 ] = 0;
....
}
The filename array consists of 14 items, but the it_riff_dsmf_process_sample function accesses the 14th item, which lies outside the array bounds. Developers often make this mistake because they forget that array indexing in C/C++ starts with 0 and ends with a value that is 1 less than the array size (in this case, the value is 13).
Let's take a look at another similar error. Here is an error from the Wolfenstein 3D project, a computer game by id Software.
typedef struct bot_state_s
{
...
char teamleader[32]; //netname of the team leader
...
} bot_state_t;
void BotMatch_StartTeamLeaderShip(
bot_state_t *bs, bot_match_t *match)
{
...
bs->teamleader[sizeof( bs->teamleader )] = '\0'; // <=
...
}
Here, the sizeof(Array) returns the array size. To access the last item, we need to subtract 1 from the sizeof(Array) result.
Note: the developers' method of accessing the last item is unreliable because it only works for arrays that contain items of 1-byte size, such as char or unsigned char. A more correct way to get the index of the last item is as follows:
const size_t lastPos = sizeof(bs->teamleader) /
sizeof(bs->teamleader[0]) - 1;
bs->teamleader[lastPos] = '\0';
Here we get the total array size in bytes and divide it by the size of the first item, thus we get the number of items in the array. At the end, all that's have left to do is subtract one. The obtained value will be the index of the last item in the array.
Even the above fix is not a good one. If you write in C++, you have safer and more convenient approaches to handle arrays. We have described them in detail in the article "How not to check array size in C++" in the section "Modern C++: correct evaluation of element numbers in arrays and containers."
Here you can learn more about such errors found through the static analysis method.
0