new module 'fenv'
When writing the lib/fpe-trapping.h file (needed to verify the quiet vs. signalling NaNs, which in turn was needed for testing the totalorder* functions), I was disappointed by the complexity of this file. Ideally it would contain just two statements: feclearexcept (FE_INVALID); feenableexcept (FE_INVALID); but then various portability problems were encountered. Following the Gnulib philosophy, these portability fixes should be hidden behind a GNU-like . Here comes the module for the header file. More modules to come in the next days. There is special code for each CPU, because many CPUs have their own quirks: - x86_64 has two floating point units (387 unit and SSE unit). Recall the 387 unit's "we compute everything with 80-bits 'long double's, whether you like it or not" philosophy, that has killed the reproducibility of numerical programs' results for decades. - i386 has one or two floating point units (387 always, SSE unit often). - aarch64 may or may not support trapping on floating-point exceptions. - arm likewise. Also armv5 has only software float routines, with no support for floating-point exceptions and only one rounding direction. - riscv does not support trapping on floating-point exceptions at all. - alpha does not support "inexact" floating-point exceptions well. It also requires system calls to modify the floating-point control word. - m68k has 3 bits for "Invalid operation", not just one. Also it has 'double's that deviate from IEEE 754. - powerpc has its control word stored in a floating-point register, not in an integer-like register. - hppa likewise. - sh4 has only two rounding directions, not four. - ia64, like x86_64 and i386, has bits that are set when traps for a certain floating-point exception are *disabled* (the opposite of all other CPUs). Only mips, s390, sparc, loongarch are somewhat sane. Bruno 2023-10-26 Bruno Haible fenv: Add tests. * tests/test-fenv.c: New file. * modules/fenv-tests: New file. fenv: New module. * lib/fenv.in.h: New file, based on glibc. * m4/fenv_h.m4: New file. * modules/fenv: New file. * doc/posix-headers/fenv.texi: Mention the new module. From b536e9d30d31345f197ccf219378ed3142fc6beb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 27 Oct 2023 03:43:15 +0200 Subject: [PATCH 1/2] fenv: New module. * lib/fenv.in.h: New file, based on glibc. * m4/fenv_h.m4: New file. * modules/fenv: New file. * doc/posix-headers/fenv.texi: Mention the new module. --- ChangeLog | 8 + doc/posix-headers/fenv.texi | 8 +- lib/fenv.in.h | 489 m4/fenv_h.m4| 98 modules/fenv| 87 +++ 5 files changed, 686 insertions(+), 4 deletions(-) create mode 100644 lib/fenv.in.h create mode 100644 m4/fenv_h.m4 create mode 100644 modules/fenv diff --git a/ChangeLog b/ChangeLog index fed7803763..b89af7a969 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2023-10-26 Bruno Haible + + fenv: New module. + * lib/fenv.in.h: New file, based on glibc. + * m4/fenv_h.m4: New file. + * modules/fenv: New file. + * doc/posix-headers/fenv.texi: Mention the new module. + 2023-10-25 Paul Eggert base32: new function isubase32; also, tune. diff --git a/doc/posix-headers/fenv.texi b/doc/posix-headers/fenv.texi index 2e7d10d29e..36c636d7db 100644 --- a/doc/posix-headers/fenv.texi +++ b/doc/posix-headers/fenv.texi @@ -3,15 +3,15 @@ POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fenv.h.html} -Gnulib module: --- +Gnulib module: fenv Portability problems fixed by Gnulib: @itemize +@item +This header file is missing on some platforms: +FreeBSD 5.2.1, NetBSD 5.0, OpenBSD 3.8, AIX 5.1, IRIX 6.5, Cygwin 1.7.7, MSVC 9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This header file is missing on some platforms: -FreeBSD 5.2.1, NetBSD 5.0, OpenBSD 3.8, AIX 5.1, IRIX 6.5, Cygwin 1.7.7, MSVC 9. @end itemize diff --git a/lib/fenv.in.h b/lib/fenv.in.h new file mode 100644 index 00..c52d0e0ccb --- /dev/null +++ b/lib/fenv.in.h @@ -0,0 +1,489 @@ +/* A GNU-like . + + Copyright (C) 1997-2023 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If
Re: [PATCH] base32, base64: disallow non-canonical encodings
On 26/10/2023 16:38, Pádraig Brady wrote: Unconditionally disallow encodings that don't have appropriate zero bits before padding characters. This handles one class of encoding variations discussed at: https://eprint.iacr.org/2022/361.pdf Note the other variations discussed there, due to optional padding characters are already disallowed. * lib/base32.c: Check that discarded bits in the encoding are zero. * lib/base64.c: Likewise. * tests/test-base32.c: Add test cases. * tests/test-base64.c: Likewise. To give a little more context, this will avoid round trip issues like the following, by failing early: $ echo "HelloWorld==" | base64 -d | base64 HelloWorlQ== In general that would make the decoder a bit better at detecting corruption in the encoded stream, and more resilient to attacks where users tweak the encoded stream for nefarious purposes. I can't see any legitimate case where one would not want/have zero bits in this case. Note RFC4648 says: "In some environments, the alteration is critical and therefore decoders MAY chose to reject an encoding if the pad bits have not been set to zero." So it's within spec, but I don't see a reason why you would want the behavior of allowing non zero pad bits. cheers, Pádraig.
[PATCH] base32, base64: disallow non-canonical encodings
Unconditionally disallow encodings that don't have appropriate zero bits before padding characters. This handles one class of encoding variations discussed at: https://eprint.iacr.org/2022/361.pdf Note the other variations discussed there, due to optional padding characters are already disallowed. * lib/base32.c: Check that discarded bits in the encoding are zero. * lib/base64.c: Likewise. * tests/test-base32.c: Add test cases. * tests/test-base64.c: Likewise. --- ChangeLog | 8 lib/base32.c| 18 ++ lib/base64.c| 9 + tests/test-base32.c | 15 +++ tests/test-base64.c | 9 + 5 files changed, 59 insertions(+) diff --git a/ChangeLog b/ChangeLog index fed7803763..2a42cd4217 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2023-10-26 Pádraig Brady + + base32, base64: disallow non-canonical encodings + * lib/base32.c: Check that discarded bits in the encoding are zero. + * lib/base64.c: Likewise. + * tests/test-base32.c: Add test cases. + * tests/test-base64.c: Likewise. + 2023-10-25 Paul Eggert base32: new function isubase32; also, tune. diff --git a/lib/base32.c b/lib/base32.c index 2d692a2b38..132c01df64 100644 --- a/lib/base32.c +++ b/lib/base32.c @@ -354,6 +354,10 @@ decode_8 (char const *restrict in, idx_t inlen, if (in[3] != '=' || in[4] != '=' || in[5] != '=' || in[6] != '=' || in[7] != '=') return_false; + + /* Reject non-canonical encodings. */ + if (base32_to_int[to_uchar (in[1])] & 0x03) +return_false; } else { @@ -372,6 +376,10 @@ decode_8 (char const *restrict in, idx_t inlen, { if (in[5] != '=' || in[6] != '=' || in[7] != '=') return_false; + + /* Reject non-canonical encodings. */ + if (base32_to_int[to_uchar (in[3])] & 0x0F) +return_false; } else { @@ -389,6 +397,10 @@ decode_8 (char const *restrict in, idx_t inlen, { if (in[6] != '=' || in[7] != '=') return_false; + + /* Reject non-canonical encodings. */ + if (base32_to_int[to_uchar (in[4])] & 0x01) +return_false; } else { @@ -415,6 +427,12 @@ decode_8 (char const *restrict in, idx_t inlen, --*outleft; } } + else +{ + /* Reject non-canonical encodings. */ + if (base32_to_int[to_uchar (in[6])] & 0x07) +return_false; +} } } } diff --git a/lib/base64.c b/lib/base64.c index 59a2135bf1..1f53498bb3 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -396,6 +396,10 @@ decode_4 (char const *restrict in, idx_t inlen, if (in[3] != '=') return_false; + + /* Reject non-canonical encodings. */ + if (base64_to_int[to_uchar (in[1])] & 0x0F) +return_false; } else { @@ -416,6 +420,11 @@ decode_4 (char const *restrict in, idx_t inlen, { if (inlen != 4) return_false; + + /* Reject non-canonical encodings. */ + if (base64_to_int[to_uchar (in[2])] & 0x03) +return_false; + } else { diff --git a/tests/test-base32.c b/tests/test-base32.c index 2e7d3c53b3..16fb982edb 100644 --- a/tests/test-base32.c +++ b/tests/test-base32.c @@ -256,5 +256,20 @@ main (void) ok = base32_decode_alloc_ctx (NULL, "AABBAA=A", 8, , ); ASSERT (!ok); + ok = base32_decode_alloc_ctx (NULL, "FZ==", 8, , ); + ASSERT (!ok); + + ok = base32_decode_alloc_ctx (NULL, "FYXB", 8, , ); + ASSERT (!ok); + + ok = base32_decode_alloc_ctx (NULL, "FYXC5===", 8, , ); + ASSERT (!ok); + + ok = base32_decode_alloc_ctx (NULL, "FYXC4LR=", 8, , ); + ASSERT (!ok); + + ok = base32_decode_alloc_ctx (NULL, "FZ==FY==", 16, , ); + ASSERT (!ok); + return 0; } diff --git a/tests/test-base64.c b/tests/test-base64.c index 5196db09f4..0da5f99054 100644 --- a/tests/test-base64.c +++ b/tests/test-base64.c @@ -233,5 +233,14 @@ main (void) ok = base64_decode_alloc_ctx (NULL, "aax=X", 5, , ); ASSERT (!ok); + ok = base64_decode_alloc_ctx (NULL, "SGVsbG9=", 8, , ); + ASSERT (!ok); + + ok = base64_decode_alloc_ctx (NULL, "TR==", 4, , ); + ASSERT (!ok); + + ok = base64_decode_alloc_ctx (NULL, "TWF=TWE=", 8, , ); + ASSERT (!ok); + return 0; } -- 2.41.0