NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

toolchain/60289: NetBSD 11 gcc mis-optimises some NULL checks



>Number:         60289
>Category:       toolchain
>Synopsis:       NetBSD 11 gcc mis-optimises some NULL checks
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    toolchain-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat May 23 18:45:00 +0000 2026
>Originator:     Manuel Bouyer
>Release:        NetBSD 11.0_RC4
>Organization:
>Environment:
System: NetBSD armandeche.soc.lip6.fr 10.1_STABLE NetBSD 10.1_STABLE (GENERIC_CAN) #36: Mon Oct 13 12:20:13 CEST 2025 bouyer%armandeche.soc.lip6.fr@localhost:/local/armandeche1/tmp/build/amd64/obj/local/armandeche2/netbsd-10/src/sys/arch/amd64/compile/GENERIC_CAN amd64
Architecture: x86_64
Machine: amd64
>Description:
	I tried updating a server from 10.1_STABLE to 11.0_RC4 and got a
	panic within minutes, related to a NULL pointer dereference.
	The issue is in ipf_fastroute(), but the code looks good and
	dissasembly shows that gcc dropped a NULL pointer check.

	I've been able to reproduce it with a simple test funtion (see
	How-To-Repeat). It seems that construct like
	if (fdp != &fr->fr_dif)
	causes gcc to assume (wrongly) that fr cannot be NULL. 
	This happens at -O2 or highter, -O1 produces the expected code.

>How-To-Repeat:
cat > test-misopt.h << EOF
typedef struct foo {
	void *fp;
} foo_t;

typedef struct bar {
	void *bp;
	foo_t foo;
	int flags;
} bar_t;

void testf(foo_t *, bar_t *);
EOF
cat > test-misopt.c << EOF
#include <stdio.h>
#include "test-misopt.h"


void
testf(foo_t *foop, bar_t *barp)
{
	if (&barp->foo != foop) {
		printf("A ");
		if (!barp || !(barp->flags & 0x01)) {
			printf("B ");
		}
		printf("C ");
	}
	printf("D\n");
}
EOF
/home/build/amd64/obj/netbsd-11/tooldir/bin/x86_64--netbsd-gcc -g -c -O2 test-misopt.c
gdb  -ex "disas /s testf" test-misopt.o
and notice:
10                      if (!barp || !(barp->flags & 0x01)) {
   0x0000000000000021 <+33>:    testb  $0x1,0x10(%rbx)
   0x0000000000000025 <+37>:    je     0x4d <testf+77>

%rsi or %rbx is never tested for 0.

>Fix:
	#pragma GCC optimize ("O1")
	before the affected funtion works around it
	But this behavior is worrisome




Home | Main Index | Thread Index | Old Index