[OT] Money for nothing, and your bit flips for free?

Jacob Fugal lukfugl at gmail.com
Thu Feb 8 09:47:33 MST 2007


On 2/7/07, Steve <smorrey at gmail.com> wrote:
> It appears that it's safe...

No, it's not. You're just lucky.

I've reworked the inside of the loop to show what's going on:

===
#include <iostream>

int main(int agc, char *argv[]) {
	int y = 0;
	std::string s = argv[1];

	std::cout << "String length is: " << s.length() << std::endl;
	do {
		std::cout << "Would flip position " << y
			<< " from '" << (signed int)s[y]
			<< "' to '"  << (signed int)~s[y]
			<< "'" << std::endl;
	} while (y++ <= s.length());

	return(0);
}
===

The output:

===
$ g++ -O3 test.cc
$ ./a.out "Hello World"
String length is: 11
Would flip position 0 from '72' to '-73'
Would flip position 1 from '101' to '-102'
Would flip position 2 from '108' to '-109'
Would flip position 3 from '108' to '-109'
Would flip position 4 from '111' to '-112'
Would flip position 5 from '32' to '-33'
Would flip position 6 from '87' to '-88'
Would flip position 7 from '111' to '-112'
Would flip position 8 from '114' to '-115'
Would flip position 9 from '108' to '-109'
Would flip position 10 from '100' to '-101'
Would flip position 11 from '0' to '-1'
Would flip position 12 from '0' to '-1'
===

Since the string length is 11, valid indexes should be 0 through 10,
but this loop indexes all the way up to 12. Similarly, for the empty
string, we'd expect no bits flipped, but:

===
$ ./a.out ""
String length is: 0
Would flip position 0 from '0' to '-1'
Would flip position 1 from '0' to '-1'
===

In both your case and my examples, there are no overt effects. But
this is by chance. std::string is basically just a wrapper around a C
string (null terminated char*). What happens when we try to get back
the internal C string? Oops, it's not null terminated any more (we
turned the null bytes into 0xff bytes). What if there's some data
placed in memory right next to the internal C string for our
std::string? We've just twiddled the first bit of that data,
corrupting it. What if the internal C string for our std::string is
placed right at the edge of the memory allocated to our process? When
we index past the end, we attempt to access memory outside our process
and we get the infamous segfault. Just because nothing bad *did*
happen, doesn't mean nothing bad *can* happen.

Jacob Fugal



More information about the PLUG mailing list