Module Name: src Committed By: riastradh Date: Mon Jun 17 18:16:58 UTC 2024
Modified Files: src/lib/libc/compat/gen: compat_ldexp_ieee754.c Log Message: libc ldexp(3): Avoid undefined behaviour in arithmetic overflow. PR lib/58347 To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/lib/libc/compat/gen/compat_ldexp_ieee754.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/compat/gen/compat_ldexp_ieee754.c diff -u src/lib/libc/compat/gen/compat_ldexp_ieee754.c:1.8 src/lib/libc/compat/gen/compat_ldexp_ieee754.c:1.9 --- src/lib/libc/compat/gen/compat_ldexp_ieee754.c:1.8 Thu May 21 05:56:31 2020 +++ src/lib/libc/compat/gen/compat_ldexp_ieee754.c Mon Jun 17 18:16:58 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: compat_ldexp_ieee754.c,v 1.8 2020/05/21 05:56:31 riastradh Exp $ */ +/* $NetBSD: compat_ldexp_ieee754.c,v 1.9 2024/06/17 18:16:58 riastradh Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: compat_ldexp_ieee754.c,v 1.8 2020/05/21 05:56:31 riastradh Exp $"); +__RCSID("$NetBSD: compat_ldexp_ieee754.c,v 1.9 2024/06/17 18:16:58 riastradh Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -115,17 +115,31 @@ ldexp(double val, int expon) /* * u.v is now normalized and oldexp has been adjusted if necessary. - * Calculate the new exponent and check for underflow and overflow. + * We have + * + * 0 <= oldexp <= DBL_EXP_INFNAN, + * + * but + * + * INT_MIN <= expon <= INT_MAX. + * + * Check for underflow and overflow, and if none, calculate the + * new exponent. */ - newexp = oldexp + expon; - - if (newexp >= DBL_EXP_INFNAN || - (oldexp >= 0 && expon >= DBL_EXP_INFNAN)) { + if (expon >= DBL_EXP_INFNAN - oldexp) { /* * The result overflowed; return +/-Inf. */ return overflow(val); - } else if (newexp <= 0) { + } + + /* + * We now have INT_MIN <= oldexp + expon <= DBL_EXP_INFNAN <= INT_MAX, + * so the arithmetic is safe. + */ + newexp = oldexp + expon; + + if (newexp <= 0) { /* * The output number is either denormal or underflows (see * comments in machine/ieee.h).