Sujet : Re: A Famous Security Bug
De : ram (at) *nospam* zedat.fu-berlin.de (Stefan Ram)
Groupes : comp.lang.cDate : 27. Mar 2024, 11:30:31
Autres entêtes
Organisation : Stefan Ram
Message-ID : <memset-20240327112617@ram.dialup.fu-berlin.de>
References : 1
ram@zedat.fu-berlin.de (Stefan Ram) wrote or quoted:
A "famous security bug":
void f( void )
{ char buffer[ MAX ];
/* . . . */
memset( buffer, 0, sizeof( buffer )); }
. Can you see what the bug is?
(I have already read the answer; I post it as a pastime.)
I was reading this under the heading "State postconditions".
It was suggested that the code should rather be:
void f()
{ char buffer[MAX];
/* . . . */
memset( buffer, 0, sizeof( buffer ));
Ensures( buffer[ 0 ]== 0 ); }
("Ensures" states a postcondition). Now, according to the text
I read, the compiler cannot eliminate the "memset" anymore.
Here are some thoughts of mine on this:
With the "buffer[ 0 ]== 0", I wonder, as per the "as if rule",
whether the compiler would still be permitted to replace
the memset by just "buffer[ 0 ]= 0;".
So, what would be a bit more "paranoid" would then be:
for( size_t i = 0; i < sizeof( buffer ); ++i )
Ensures( buffer[ i ]== 0 );
or,
i = mylib_random( sizeof( buffer ));
Ensures( buffer[ i ]== 0 );
. How could one implement "Ensures" in C? The first thing that
comes to mind is a call to "assert" of course.
But I also have to think of an "escape" Chandler Carruth mentioned
it in one talk. IIRC, it was something along the lines of
static void escape( volatile void * p )
{ asm volatile( "" : : "g"(p) : "memory" ); }
(which might not be standard C). Now, if you call "escape( buffer )"
at the end of the definition of the function "f" above, the compiler
knows that the contents of buffer has become visible to the outside
world, so that the effects of the "memset" operation become visible
externally, which means that the "memset" call cannot be elided.