File: cert_exp35_c.i

package info (click to toggle)
frama-c 20161101%2Bsilicon%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 42,324 kB
  • ctags: 35,695
  • sloc: ml: 200,142; ansic: 31,465; makefile: 2,334; sh: 1,643; lisp: 259; python: 85; asm: 26
file content (36 lines) | stat: -rw-r--r-- 1,399 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void printf(const char* c,...);

struct X { char a[6]; };

struct X addressee(void) {
  struct X result = { "world" };
  return result;
}

int main(void) {
  printf("Hello, %s!\n", addressee().a);
  return 0;
}

/*
From https://www.securecoding.cert.org/confluence/display/seccode/EXP35-C.+Do+not+access+or+modify+an+array+in+the+result+of+a+function+call+after+a+subsequent+sequence+point
 
This solution is problematic because of three inherent properties of C:

In C, the lifetime of a return value ends at the next sequence point. 
Consequently by the time printf() is called, the struct returned by 
the addressee() call is no longer considered valid, and may have been 
overwritten.
C function arguments are passed by value. As a result, copies are made 
of all objects generated by the arguments. For example, a copy is made of the 
pointer to "Hello, %s!\n". Under most circumstances, these copies protect you 
from the effects of sequence points described earlier.
Finally, C implicitly converts arrays to pointers when passing them as 
function arguments. This means that a copy is made of the pointer to the 
addresee().a array, and that pointer copy is passed to printf(). 
But the array data itself is not copied, and may no longer exist when printf()
is called.
Consequently when printf() tries to dereference the pointer passed as 
its 2nd argument, it is likely to find garbage.

*/