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:

NetBSD Home
NetBSD PR Database Search

(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.