Bug 47732 - counter decremented to zero not detected when other counter overflows
Summary: counter decremented to zero not detected when other counter overflows
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.3.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-02-14 14:34 UTC by Jan Koen Annot
Modified: 2011-02-15 14:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
preprocessor output (354 bytes, text/plain)
2011-02-14 14:34 UTC, Jan Koen Annot
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Koen Annot 2011-02-14 14:34:42 UTC
Created attachment 23336 [details]
preprocessor output

gcc version 4.3.3 [gcc-4_3-branch revision 147732] (SUSE Linux)

Target: x86_64-suse-linux

Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.3 --enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --program-suffix=-4.3 --enable-linux-futex --without-system-libunwind --with-cpu=generic --build=x86_64-suse-linux

COLLECT_GCC_OPTIONS='-v' '-save-temps' '-O2' '-mtune=generic'
 /usr/lib64/gcc/x86_64-suse-linux/4.3/cc1 -E -quiet -v verify_counter_nonzero.c -mtune=generic -O2 -fpch-preprocess -o verify_counter_nonzero.i

A local counter (named lCounter) is decremented in a while-loop, and the loop must stop when the counter reaches zero.
In the same loop, a second local counter (lVeryHighCounter) is incremented and overflows in the same cycle where the first counter reaches zero.
The overflow of the second counter seems to trigger that it is not detected that the first counter reaches zero: (lCounter != 0) remains false.
A static counter (named sCounter) is used to observe what happens and to stop the program as soon as the bug is observed.

The used -O2 option is needed to reproduce the bug.
Using -O1 or -O3 does not reproduce the bug.

extern int printf(const char *, ...);
extern void exit(int);

static int	sCounter	= 3;

void	verify_counter_nonzero(
	int	aDummy
)
{
	printf("sCounter value: %d\n", sCounter);

	if (sCounter == 0) {
		printf("Compiler bug detected! This function should not be called when counter reached 0.\n");

		exit(0);
	}
}

int	main()
{
	int	lCounter		= 3;
	int	lVeryHighCounter	= 0x80000000 - 3;

	while (lCounter != 0) {
		verify_counter_nonzero(lVeryHighCounter);

		sCounter		-= 1;
		lCounter		-= 1;
		lVeryHighCounter	+= 1;

		/* In the same cycle where lCounter is decremented to 0, 
		   lVeryHighCounter is incremented (and overflows) from 0x7FFFFFFF to 0x80000000.
		   This seems to trigger the bug: the loop condition (lCounter != 0) should become false,
		   but remains true.
		*/
	}

	printf("Compiler bug not detected! Loop terminated correctly.\n");
}
Comment 1 Andrew Pinski 2011-02-14 18:22:17 UTC
"lVeryHighCounter is incremented (and overflows) from 0x7FFFFFFF to
0x80000000."

And overflow is undefined in C/C++ so you are invoking undefined behavior here.
Comment 2 Jan Koen Annot 2011-02-15 14:21:16 UTC
(In reply to comment #1)
> And overflow is undefined in C/C++ so you are invoking undefined behavior here.

Wow! This is an eye-opener for me! I am quite accustomed to assume two's complement arithmetic with implicit wrap-around for signed integers.

After your remark I googled a bit and found several articles about undefined behavior, e.g. John Regehr's "A Guide to Undefined Behavior in C and C++, Part 1".
Very instructive.