CWE-131: Incorrect Calculation of Buffer Size

Description

The product does not correctly calculate the size to be used when allocating a buffer, which could lead to a buffer overflow.

Submission Date :

July 19, 2006, midnight

Modification Date :

2023-06-29 00:00:00+00:00

Organization :

MITRE
Example Vulnerable Codes

Example - 1

The following code allocates memory for a maximum number of widgets. It then gets a user-specified number of widgets, making sure that the user does not request too many. It then initializes the elements of the array using InitializeWidget(). Because the number of widgets can vary for each request, the code inserts a NULL pointer to signify the location of the last widget.


ExitError("Incorrect number of widgets requested!");
WidgetList[i] = InitializeWidget();
int i;unsigned int numWidgets;Widget **WidgetList;numWidgets = GetUntrustedSizeValue();if ((numWidgets == 0) || (numWidgets > MAX_NUM_WIDGETS)) {}WidgetList = (Widget **)malloc(numWidgets * sizeof(Widget *));printf("WidgetList ptr=%p\n", WidgetList);for(i=0; i<numWidgets; i++) {}WidgetList[numWidgets] = NULL;showWidgets(WidgetList);

However, this code contains an off-by-one calculation error (CWE-193). It allocates exactly enough space to contain the specified number of widgets, but it does not include the space for the NULL pointer. As a result, the allocated buffer is smaller than it is supposed to be (CWE-131). So if the user ever requests MAX_NUM_WIDGETS, there is an out-of-bounds write (CWE-787) when the NULL is assigned. Depending on the environment and compilation settings, this could cause memory corruption.

Example - 2

The following image processing code allocates a table for images.


img_t table_ptr; /*struct containing img data, 10kB each*/int num_imgs;...num_imgs = get_num_imgs();table_ptr = (img_t*)malloc(sizeof(img_t)*num_imgs);...

This code intends to allocate a table of size num_imgs, however as num_imgs grows large, the calculation determining the size of the list will eventually overflow (CWE-190). This will result in a very small list to be allocated instead. If the subsequent code operates on the list as if it were num_imgs long, it may result in many types of out-of-bounds problems (CWE-119).

Example - 3

This example applies an encoding procedure to an input string and stores it into a buffer.


die("user string too long, die evil hacker!");

dst_buf[dst_index++] = '&';dst_buf[dst_index++] = 'a';dst_buf[dst_index++] = 'm';dst_buf[dst_index++] = 'p';dst_buf[dst_index++] = ';';

// /* encode to &lt; */// 

if( '&' == user_supplied_string[i] ){}else if ('<' == user_supplied_string[i] ){}else dst_buf[dst_index++] = user_supplied_string[i];
int i, dst_index;char *dst_buf = (char*)malloc(4*sizeof(char) * MAX_SIZE);if ( MAX_SIZE <= strlen(user_supplied_string) ){}dst_index = 0;for ( i = 0; i < strlen(user_supplied_string); i++ ){}return dst_buf;char * copy_input(char *user_supplied_string){}

The programmer attempts to encode the ampersand character in the user-controlled string, however the length of the string is validated before the encoding procedure is applied. Furthermore, the programmer assumes encoding expansion will only expand a given character by a factor of 4, while the encoding of the ampersand expands by 5. As a result, when the encoding procedure expands the string it is possible to overflow the destination buffer if the attacker provides a string of many ampersands.

Example - 4

The following code is intended to read an incoming packet from a socket and extract one or more headers.


ExitError("too many headers!");
DataPacket *packet;int numHeaders;PacketHeader *headers;sock=AcceptSocketConnection();ReadPacket(packet, sock);numHeaders =packet->headers;if (numHeaders > 100) {}headers = malloc(numHeaders * sizeof(PacketHeader);ParsePacketHeaders(packet, headers);

The code performs a check to make sure that the packet does not contain too many headers. However, numHeaders is defined as a signed int, so it could be negative. If the incoming packet specifies a value such as -3, then the malloc calculation will generate a negative number (say, -300 if each header can be a maximum of 100 bytes). When this result is provided to malloc(), it is first converted to a size_t type. This conversion then produces a large value such as 4294966996, which may cause malloc() to fail or to allocate an extremely large amount of memory (CWE-195). With the appropriate negative numbers, an attacker could trick malloc() into using a very small positive number, which then allocates a buffer that is much smaller than expected, potentially leading to a buffer overflow.

Example - 5

The following code attempts to save three different identification numbers into an array. The array is allocated from memory using a call to malloc().


// /* Allocate space for an array of three ids. */// 
// /* Populate the id array. */// 
int *id_sequence;id_sequence = (int*) malloc(3);if (id_sequence == NULL) exit(1);id_sequence[0] = 13579;id_sequence[1] = 24680;id_sequence[2] = 97531;

The problem with the code above is the value of the size parameter used during the malloc() call. It uses a value of '3' which by definition results in a buffer of three bytes to be created. However the intention was to create a buffer that holds three ints, and in C, each int requires 4 bytes worth of memory, so an array of 12 bytes is needed, 4 bytes for each int. Executing the above code could result in a buffer overflow as 12 bytes of data is being saved into 3 bytes worth of allocated space. The overflow would occur during the assignment of id_sequence[0] and would continue with the assignment of id_sequence[1] and id_sequence[2].

The malloc() call could have used '3*sizeof(int)' as the value for the size parameter in order to allocate the correct amount of space required to store the three ints.

Related Weaknesses

This table shows the weaknesses and high level categories that are related to this weakness. These relationships are defined to give an overview of the different insight to similar items that may exist at higher and lower levels of abstraction.

Visit http://cwe.mitre.org/ for more details.