NetBSD Problem Report #60514
From www@netbsd.org Tue Jul 28 17:30:54 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.netbsd.org", Issuer "YR2" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id D333F1A923C
for <gnats-bugs@gnats.NetBSD.org>; Tue, 28 Jul 2026 17:30:53 +0000 (UTC)
Message-Id: <20260728173052.4A27C1A923D@mollari.NetBSD.org>
Date: Tue, 28 Jul 2026 17:30:52 +0000 (UTC)
From: appease1337@proton.me
Reply-To: appease1337@proton.me
To: gnats-bugs@NetBSD.org
Subject: libm/hppa: feholdexcept() does not clear floating-point status flags
X-Send-Pr-Version: www-1.0
X-From4GNATS: "appease1337@proton.me via gnats" <gnats-admin@NetBSD.org>
>Number: 60514
>Notify-List: riastradh
>Category: lib
>Synopsis: libm/hppa: feholdexcept() does not clear floating-point status flags
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: analyzed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Jul 28 17:35:00 +0000 2026
>Closed-Date:
>Last-Modified: Tue Jul 28 17:48:48 +0000 2026
>Originator: Mark H. (aka maki73)
>Release: 10.1
>Organization:
>Environment:
NetBSD 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/hppa/compile/GENERIC hppa
>Description:
feholdexcept() on PA-RISC/hppa NetBSD fails to clear floating-point status flags (exceptions) and instead only sets non-stop mode.
In the source src/lib/libm/arch/hppa/fenv.c feclearexcept() first shifts left by `FE_FLAGS_SHIFT` to clear status flags, whereas feholdexcept() simply performs
r &= ~FE_ALL_EXCEPT;
not shifting. This sets non-stop mode but does not clear status flags, contradicting its own comment right above the function.
Also, the existing shift logic in the file seems to be UB-adjacent (e.g., in feclearexcept() when excepts=FE_ALL_EXCEPT shift becomes FE_ALL_EXCEPT << FE_FLAGS_SHIFT, if FE_FLAGS_SHIFT is 27 and FE_ALL_EXCEPT is 31 then it's UB because 32-bit int cannot represent 31 * 2^27), but this is its own separate problem.
This also violates the C Standard
See:
https://man.netbsd.org/fenv.3
ISO/IEC 9899:2024 \S 7.6.6.2 \P 2 (or equivalently C99 \S 7.6.4.2 \P 2)
and ISO/IEC 9899:2024 \S 6.5.8 \P 4 for UB in the feclearexcept's shift
>How-To-Repeat:
$ uname -a
NetBSD 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/hppa/compile/GENERIC hppa
$ cat reproducer.c
#include <stdio.h>
#include <stdlib.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
#ifndef FE_DIVBYZERO
# error "reproducer requires availability of FE_DIVBYZERO!"
#endif
int main(void) {
/* raise any floating-point exception
*/
if (feraiseexcept(FE_DIVBYZERO) != 0) {
goto fail;
}
/* ISO/IEC 9899:2024 \S 7.6.6.2 \P 2 (equivalently to C99 \S 7.6.4.2 \P 2)
states that feholdexcept() function besides other duties does quote:
".. pointed to by envp, **clears the floating-point status flags**, and then ..."
IEEE Std 1003.1-2017 (aka POSIX) defers to the ISO C standard here.
*/
fenv_t env;
if (feholdexcept(&env) != 0) {
goto fail;
}
/* if the feholdexcept() is correct, this branch should
not be taken
*/
if (fetestexcept(FE_DIVBYZERO) != 0) {
fprintf(stderr, "bug: feholdexcept() did not clear the floating-point status flags!\n");
return EXIT_FAILURE;
}
printf("feholdexcept correctly cleared floating-point status flags.\n");
return EXIT_SUCCESS;
fail:
fprintf(stderr, "unexpected failure!\n");
return EXIT_FAILURE;
}
$ cc reproducer.c -lm -o reproducer
$ ./reproducer
bug: feholdexcept() did not clear the floating-point status flags!
$ cc -lm -S reproducer.c
$ cat reproducer.s | grep "bl" # check that compiler preserved all calls
.globl main
bl feraiseexcept,%r2
bl feholdexcept,%r2
bl fetestexcept,%r2
bl fwrite,%r2
bl puts,%r2
bl fwrite,%r2
$
>Fix:
Fix can be done similar to as shown below:
@@ -30,6 +30,7 @@
#include <assert.h>
#include <fenv.h>
+#include <stdint.h>
#ifdef __weak_alias
__weak_alias(feclearexcept,_feclearexcept)
@@ -275,12 +276,15 @@
feholdexcept(fenv_t *envp)
{
fenv_t r;
+ uint32_t mask;
_DIAGASSERT(envp != NULL);
r = readfpsr();
*envp = r;
- r &= ~FE_ALL_EXCEPT;
+ mask = (uint32_t)FE_ALL_EXCEPT
+ mask |= mask << FE_FLAGS_SHIFT;
+ r &= ~mask;
writefpsr(r);
/* Success */
NOTE: Test this fix before applying
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: port-hppa-maintainer->lib-bug-people
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Tue, 28 Jul 2026 17:47:06 +0000
Responsible-Changed-Why:
There's a much bigger problem here: we seem to have zero tests of
feholdexcept! I bet it's broken on more than just hppa...
State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Tue, 28 Jul 2026 17:47:06 +0000
State-Changed-Why:
problem analyzed
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.