CWE-789: Memory Allocation with Excessive Size Value

Description

The product allocates memory based on an untrusted, large size value, but it does not ensure that the size is within expected limits, allowing arbitrary amounts of memory to be allocated.

Submission Date :

Oct. 21, 2009, midnight

Modification Date :

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

Organization :

MITRE
Example Vulnerable Codes

Example - 1

Consider the following code, which accepts an untrusted size value and allocates a buffer to contain a string of the given size.


// /* ignore integer overflow (CWE-190) for this example */// 
unsigned int size = GetUntrustedInt();unsigned int totBytes = size * sizeof(char);char *string = (char *)malloc(totBytes);InitializeString(string);

Suppose an attacker provides a size value of:

12345678

This will cause 305,419,896 bytes (over 291 megabytes) to be allocated for the string.

Example - 2

Consider the following code, which accepts an untrusted size value and uses the size as an initial capacity for a HashMap.


unsigned int size = GetUntrustedInt();HashMap list = new HashMap(size);

The HashMap constructor will verify that the initial capacity is not negative, however there is no check in place to verify that sufficient memory is present. If the attacker provides a large enough value, the application will run into an OutOfMemoryError.

Example - 3

This code performs a stack allocation based on a length calculation.


int a = 5, b = 6;size_t len = a - b;char buf[len];    // Just blows up the stack}

Since a and b are declared as signed ints, the "a - b" subtraction gives a negative result (-1). However, since len is declared to be unsigned, len is cast to an extremely large positive number (on 32-bit systems - 4294967295). As a result, the buffer buf[len] declaration uses an extremely large size to allocate on the stack, very likely more than the entire computer's memory space.

Miscalculations usually will not be so obvious. The calculation will either be complicated or the result of an attacker's input to attain the negative value.

Example - 4

This example shows a typical attempt to parse a string with an error resulting from a difference in assumptions between the caller to a function and the function's action.


// // Note space at the end of the string - assume all strings have preamble with space// 
// ... Do processing here if we get this far// int pre_len = sizeof("preamble: ");char buf[pre_len - msg_len];
int proc_msg(char *s, int msg_len){}char *s = "preamble: message\n";char *sl = strchr(s, ':');        // Number of characters up to ':' (not including space)int jnklen = sl == NULL ? 0 : sl - s;    // If undefined pointer, use zero lengthint ret_val = proc_msg ("s",  jnklen);    // Violate assumption of preamble length, end up with negative value, blow out stack

The buffer length ends up being -1, resulting in a blown out stack. The space character after the colon is included in the function calculation, but not in the caller's calculation. This, unfortunately, is not usually so obvious but exists in an obtuse series of calculations.

Example - 5

The following code obtains an untrusted number that is used as an index into an array of messages.


my $num = GetUntrustedNumber();my @messages = ();$messages[$num] = "Hello World";

The index is not validated at all (CWE-129), so it might be possible for an attacker to modify an element in @messages that was not intended. If an index is used that is larger than the current size of the array, the Perl interpreter automatically expands the array so that the large index works.

If $num is a large value such as 2147483648 (1<<31), then the assignment to $messages[$num] would attempt to create a very large array, then eventually produce an error message such as:

Out of memory during array extend

This memory exhaustion will cause the Perl program to exit, possibly a denial of service. In addition, the lack of memory could also prevent many other programs from successfully running on the system.

Example - 6

This example shows a typical attempt to parse a string with an error resulting from a difference in assumptions between the caller to a function and the function's action. The buffer length ends up being -1 resulting in a blown out stack. The space character after the colon is included in the function calculation, but not in the caller's calculation. This, unfortunately, is not usually so obvious but exists in an obtuse series of calculations.


int pre_len = sizeof("preamble: ");    // Note space at the end of the string - assume all strings have preamble with spacechar buf[pre_len - msg_len];... Do processing here and set statusreturn status;

int proc_msg(char *s, int msg_len)
{}char *s = "preamble: message\n";
char *sl = strchr(s, ':');        // Number of characters up to ':' (not including space)
int jnklen = sl == NULL ? 0 : sl - s;    // If undefined pointer, use zero length
int ret_val = proc_msg ("s",  jnklen);    // Violate assumption of preamble length, end up with negative value, blow out stack

int pre_len = sizeof("preamble: ");    // Note space at the end of the string - assume all strings have preamble with spaceif (pre_len <= msg_len) { // Log error; return error_code; }char buf[pre_len - msg_len];... Do processing here and set statusreturn status;

int proc_msg(char *s, int msg_len)
{}char *s = "preamble: message\n";
char *sl = strchr(s, ':');        // Number of characters up to ':' (not including space)
int jnklen = sl == NULL ? 0 : sl - s;    // If undefined pointer, use zero length
int ret_val = proc_msg ("s",  jnklen);    // Violate assumption of preamble length, end up with negative value, blow out stack

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.