...
Code Block | ||||
---|---|---|---|---|
| ||||
void f(int n, int * restrict p, int * restrict q) { while (n-- > 0) *p++ = *q++; } void g(void) { extern int d[100]; /* ... */ f(50, d + 50, d); /* valid */ } |
Noncompliant Code Example
In this noncompliant code example, the call h(100, a, a, a)
has undefined behavior because the object modifed by p is accessed by q and r.
Code Block | ||||
---|---|---|---|---|
| ||||
void h(size_t n, int * restrict p, int * restrict q, int * restrict r) {
for (size_t i = 0; i < n; i++)
p[i] = q[i] + r[i];
}
void j(void) {
int a[100];
h(100, a, a, a);
} |
The function g()
declares an array d
consisting of 100 int
values and then invokes f()
to copy memory from one area of the array to another. This call has undefined behavior because each of d[1]
through d[49]
is accessed through both p
and q
.
Compliant Solution
In this compliant solution, an unmodified object is aliased through two restricted pointers. Because a and b are disjoint arrays, a call of the form h(100, a, b, b)
has defined behavior, because array b is not modified within function h .
Code Block | ||||
---|---|---|---|---|
| ||||
void h(size_t n, int * restrict p, int * restrict q, int * restrict r) {
for (size_t i = 0; i < n; i++)
p[i] = q[i] + r[i];
}
void j(void) {
int a[100];
int b[100];
h(100, a, b, b);
} |
Invoking Library Functions with restrict-qualified Pointers
...
If the objects referenced by arguments to functions overlap (meaning the objects share some common memory addresses), the behavior is undefined. See also undefined behavior 68 in Appendix J of the C Standard. The result of the functions is unknown and data may be corrupted. As a result, these functions must never be passed pointers to overlapping objects. If data must be copied between objects that share common memory addresses, a copy function guaranteed to work on overlapping memory, such as memmove()
, should be used.
Noncompliant Code Example
In this noncompliant code example, the values of objects referenced by ptr1
and ptr2
become unpredictable after the call to memcpy()
because their memory areas overlap:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> void func(void) { char c_str[]= "test string"; char *ptr1 = c_str; char *ptr2; ptr2 = ptr1 + 3; memcpy(ptr2, ptr1, 6); /* ... */ } |
Compliant Solution
In this compliant solution, the call to memcpy()
is replaced with a call to memmove()
. The memmove()
function performs the same operation as memcpy()
, but copying takes place as if the n characters from the object pointed to by the source (ptr1
) are first copied into a temporary array of n characters that does not overlap the objects pointed to by the destination (ptr2
) or the source. The n characters from the temporary array are then copied into the object pointed to by the destination.
...
For formatted output functions such as printf()
, it is unlikely that a programmer would modify the format string. However, an attacker may attempt this if a program violates FIO30-C. Exclude user input from format strings and passes tainted values as part of the format string.
Noncompliant Code Example
In this noncompliant code example, the programmer is attempting to overwrite the format string with a string value read in from stdin, and to use the modified string to input subsequent values:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> /* ... */ char format[100] = "%s"; int i; float x; int n = scanf(format, format + 2, &i, &x); |
Compliant Solution
The same results can be achieved as shown in this compliant solutoin.
...