...
Microsoft has submitted a feature request to add support for the j
length modifier to a future release of Microsoft Visual Studio.
Noncompliant Code Example (extended types)
Consider the following code sample, which indicates if an aray has room for elem_count
more elements:
Code Block | ||||
---|---|---|---|---|
| ||||
/* test if we can fit elem_count chars in the space between p_current and p_max. */
bool test_ptr(unsigned int elem_count, char *p_max, char *p_current) {
int subscript_diff = p_max - p_current;
if ((p_max > p_current) && (subscript_diff > elem_count) ) {
return true;
}
return false;
}
|
Consider what happens when this function is called in the following manner on a 64-bit platform:
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned int char_count = (unsigned int) INT_MAX + 10;
char *huge_string = malloc(char_count); /* we have lots of RAM ;) */
/* ... */
if (test_ptr(3, huge_string + char_count - 1, huge_string) {
/* add 3 more elements to huge_string */
}
|
In this scenario, test_ptr()
will return false when it should return true. The result of p_max - p_current
is a ptrdiff_t
with a mathematical value of INT_MAX + 10
. However, on a 64-bit platform, if int
is still 32 bits, then when p_max - p_current
is stored into an int
, the result will be a negative value of INT_MIN + 9
. Now subscript_diff
is less than elem_count
and the comparison will fail.
Compliant Solution
In this compliant solution, we declare subscript_diff
to be a ptrdiff_t
:
Code Block | ||||
---|---|---|---|---|
| ||||
/* test if we can fit elem_count chars in the space between p_current and p_max. */
bool test_ptr(unsigned int elem_count, char *p_max, char *p_current) {
ptrdiff_t subscript_diff = p_max - p_current;
if ((p_max > p_current) && (subscript_diff > elem_count) ) {
return true;
}
return false;
}
|
On the 64-bit scenario, this code correctly returns true.
Compliant Solution (extended types)
In this compliant solution, we declare subscript_diff
to be a intmax_t
, which is, by definition, large enough to contain the difference between two pointers:
Code Block | ||||
---|---|---|---|---|
| ||||
/* test if we can fit elem_count chars in the space between p_current and p_max. */
bool test_ptr(unsigned int elem_count, char *p_max, char *p_current) {
intmax_t subscript_diff = p_max - p_current;
if ((p_max > p_current) && (subscript_diff > elem_count) ) {
return true;
}
return false;
}
|
On the 64-bit scenario, this code correctly returns true.
Because ptrdiff_t
is the official type for representing the difference between two pointers, we also could have declared subscript_diff
to be of ptrdiff_t
type.
Risk Assessment
Failure to use an appropriate conversion specifier when inputting or outputting programmer-defined integer types can result in buffer overflow and lost or misinterpreted data.
...