git: 12e0d316644a - main - vendor/bc: upgrade to version 7.0.0

From: Stefan Eßer <se_at_FreeBSD.org>
Date: Mon, 26 Aug 2024 16:28:13 UTC
The branch main has been updated by se:

URL: https://cgit.FreeBSD.org/src/commit/?id=12e0d316644a4f80f5f1f78cf07bd93def43b1ca

commit 12e0d316644a4f80f5f1f78cf07bd93def43b1ca
Author:     Stefan Eßer <se@FreeBSD.org>
AuthorDate: 2024-08-23 16:45:58 +0000
Commit:     Stefan Eßer <se@FreeBSD.org>
CommitDate: 2024-08-26 16:27:29 +0000

    vendor/bc: upgrade to version 7.0.0
    
    This is a production release to fix three bugs, none of which
    affects well formed scripts on FreeBSD:
    
    The first bug is that bc/dc will exit on macOS when the terminal
    is resized.
    
    The second bug is that an array, which should only be a function
    parameter, was accepted as part of larger expressions.
    
    The third bug is that the value stack for dc was cleared on any error.
    However, this is not how other dc behave. To bring dc more in line
    with other implementations, this behavior was changed. This change is
    why this version is a new major version.
    
    (cherry picked from commit 54d20d67e2af28d948ce2df13feb039fa10900fc)
    
    MFC after:      3 days
---
 contrib/bc/Makefile.in            |  10 +++-
 contrib/bc/NEWS.md                |  14 +++++
 contrib/bc/compile_flags.txt      |   1 +
 contrib/bc/configure.sh           | 120 ++++++++++++++++++++++++++++++--------
 contrib/bc/include/args.h         |   2 +-
 contrib/bc/include/bc.h           |   2 +-
 contrib/bc/include/dc.h           |   2 +-
 contrib/bc/include/opt.h          |   6 +-
 contrib/bc/include/ossfuzz.h      |  79 +++++++++++++++++++++++++
 contrib/bc/include/status.h       |  25 ++------
 contrib/bc/include/version.h      |   2 +-
 contrib/bc/include/vm.h           |   2 +-
 contrib/bc/manuals/dc/A.1         |   7 ++-
 contrib/bc/manuals/dc/A.1.md      |   9 ++-
 contrib/bc/manuals/dc/E.1         |   7 ++-
 contrib/bc/manuals/dc/E.1.md      |   9 ++-
 contrib/bc/manuals/dc/EH.1        |   7 ++-
 contrib/bc/manuals/dc/EH.1.md     |   9 ++-
 contrib/bc/manuals/dc/EHN.1       |   7 ++-
 contrib/bc/manuals/dc/EHN.1.md    |   9 ++-
 contrib/bc/manuals/dc/EN.1        |   7 ++-
 contrib/bc/manuals/dc/EN.1.md     |   9 ++-
 contrib/bc/manuals/dc/H.1         |   7 ++-
 contrib/bc/manuals/dc/H.1.md      |   9 ++-
 contrib/bc/manuals/dc/HN.1        |   7 ++-
 contrib/bc/manuals/dc/HN.1.md     |   9 ++-
 contrib/bc/manuals/dc/N.1         |   7 ++-
 contrib/bc/manuals/dc/N.1.md      |   9 ++-
 contrib/bc/scripts/os.c           |  59 +++++++++++++++++++
 contrib/bc/src/args.c             |   4 +-
 contrib/bc/src/bc.c               |   3 +-
 contrib/bc/src/bc_fuzzer.c        | 112 +++++++++++++++++++++++++++++++++++
 contrib/bc/src/bc_lex.c           |   2 +
 contrib/bc/src/bc_parse.c         |  23 +++++++-
 contrib/bc/src/data.c             |  59 +++++++++++++++++++
 contrib/bc/src/dc.c               |   3 +-
 contrib/bc/src/dc_fuzzer.c        | 112 +++++++++++++++++++++++++++++++++++
 contrib/bc/src/dc_lex.c           |   2 +
 contrib/bc/src/history.c          |   2 +-
 contrib/bc/src/lang.c             |   4 +-
 contrib/bc/src/lex.c              |   8 +++
 contrib/bc/src/main.c             |  21 +++++--
 contrib/bc/src/num.c              |   4 ++
 contrib/bc/src/opt.c              |  14 ++---
 contrib/bc/src/program.c          |  13 +++--
 contrib/bc/src/vm.c               |  38 ++++++++++--
 contrib/bc/tests/bc/errors/37.txt |  37 ++++++++++++
 contrib/bc/tests/bc/errors/38.txt |  37 ++++++++++++
 contrib/bc/vs/bc.vcxproj          |  18 +++---
 include/ossfuzz.h                 |  79 +++++++++++++++++++++++++
 50 files changed, 914 insertions(+), 133 deletions(-)

diff --git a/contrib/bc/Makefile.in b/contrib/bc/Makefile.in
index 4adb76ddaa17..c63dc242e79a 100644
--- a/contrib/bc/Makefile.in
+++ b/contrib/bc/Makefile.in
@@ -94,6 +94,10 @@ BC = bc
 DC = dc
 BC_EXEC = $(BIN)/$(EXEC_PREFIX)$(BC)
 DC_EXEC = $(BIN)/$(EXEC_PREFIX)$(DC)
+BC_FUZZER = $(BIN)/$(BC)_fuzzer_c
+BC_FUZZER_C = $(BIN)/$(BC)_fuzzer_C
+DC_FUZZER = $(BIN)/$(DC)_fuzzer_c
+DC_FUZZER_C = $(BIN)/$(DC)_fuzzer_C
 
 BC_TEST_OUTPUTS = tests/bc_outputs
 BC_FUZZ_OUTPUTS = tests/fuzzing/bc_outputs1 tests/fuzzing/bc_outputs2 tests/fuzzing/bc_outputs3
@@ -149,8 +153,11 @@ BC_ENABLE_NLS = %%NLS%%
 BC_EXCLUDE_EXTRA_MATH = %%EXCLUDE_EXTRA_MATH%%
 
 BC_ENABLE_AFL = %%FUZZ%%
+BC_ENABLE_OSSFUZZ = %%OSSFUZZ%%
 BC_ENABLE_MEMCHECK = %%MEMCHECK%%
 
+LIB_FUZZING_ENGINE = %%LIB_FUZZING_ENGINE%%
+
 BC_DEFAULT_BANNER = %%BC_DEFAULT_BANNER%%
 BC_DEFAULT_SIGINT_RESET = %%BC_DEFAULT_SIGINT_RESET%%
 DC_DEFAULT_SIGINT_RESET = %%DC_DEFAULT_SIGINT_RESET%%
@@ -210,7 +217,8 @@ CPPFLAGS5 = $(CPPFLAGS4) -DBC_NUM_KARATSUBA_LEN=$(BC_NUM_KARATSUBA_LEN)
 CPPFLAGS6 = $(CPPFLAGS5) -DBC_ENABLE_NLS=$(BC_ENABLE_NLS)
 CPPFLAGS7 = $(CPPFLAGS6) -D$(BC_ENABLE_EXTRA_MATH_NAME)=$(BC_ENABLE_EXTRA_MATH)
 CPPFLAGS8 = $(CPPFLAGS7) -DBC_ENABLE_HISTORY=$(BC_ENABLE_HISTORY) -DBC_ENABLE_LIBRARY=$(BC_ENABLE_LIBRARY)
-CPPFLAGS = $(CPPFLAGS8) -DBC_ENABLE_MEMCHECK=$(BC_ENABLE_MEMCHECK) -DBC_ENABLE_AFL=$(BC_ENABLE_AFL)
+CPPFLAGS9 = $(CPPFLAGS8) -DBC_ENABLE_MEMCHECK=$(BC_ENABLE_MEMCHECK) -DBC_ENABLE_AFL=$(BC_ENABLE_AFL)
+CPPFLAGS = $(CPPFLAGS9) -DBC_ENABLE_OSSFUZZ=$(BC_ENABLE_OSSFUZZ)
 CFLAGS = $(CPPFLAGS) $(BC_DEFS) $(DC_DEFS) %%CPPFLAGS%% %%CFLAGS%%
 LDFLAGS = %%LDFLAGS%%
 
diff --git a/contrib/bc/NEWS.md b/contrib/bc/NEWS.md
index 95de7e5182c4..1775fa0b6533 100644
--- a/contrib/bc/NEWS.md
+++ b/contrib/bc/NEWS.md
@@ -1,5 +1,19 @@
 # News
 
+## 7.0.0
+
+This is a production release to fix three bugs.
+
+The first bug is that `bc`/`dc` will exit on macOS when the terminal is resized.
+
+The second bug is that an array, which should only be a function parameter, was
+accepted as part of larger expressions.
+
+The third bug is that value stack for `dc` was cleared on any error. However,
+this is not how other `dc` behave. To bring `dc` more in line with other
+implementations, this behavior was changed. This change is why this version is a
+new major version.
+
 ## 6.7.6
 
 This is a production release to fix one bug.
diff --git a/contrib/bc/compile_flags.txt b/contrib/bc/compile_flags.txt
index 7a08c87f3876..3324798013c6 100644
--- a/contrib/bc/compile_flags.txt
+++ b/contrib/bc/compile_flags.txt
@@ -13,3 +13,4 @@
 -DBC_ENABLE_EXTRA_MATH=1
 -DBC_ENABLE_HISTORY=1
 -DBC_ENABLE_NLS=1
+-DBC_ENABLE_OSSFUZZ=0
diff --git a/contrib/bc/configure.sh b/contrib/bc/configure.sh
index 43bb502ea817..442165d15693 100755
--- a/contrib/bc/configure.sh
+++ b/contrib/bc/configure.sh
@@ -68,7 +68,7 @@ usage() {
 	printf '       [--man3dir=MAN3DIR]\n'
 
 	if [ "$_usage_val" -ne 0 ]; then
-		exit
+		exit "$_usage_val"
 	fi
 
 	printf '\n'
@@ -181,6 +181,8 @@ usage() {
 	printf '        Enable a build appropriate for valgrind. For development only.\n'
 	printf '    -z, --enable-fuzz-mode\n'
 	printf '        Enable fuzzing mode. THIS IS FOR DEVELOPMENT ONLY.\n'
+	printf '    -Z, --enable-ossfuzz-mode\n'
+	printf '        Enable fuzzing mode for OSS-Fuzz. THIS IS FOR DEVELOPMENT ONLY.\n'
 	printf '    --prefix PREFIX\n'
 	printf '        The prefix to install to. Overrides "$PREFIX" if it exists.\n'
 	printf '        If PREFIX is "/usr", install path will be "/usr/bin".\n'
@@ -722,6 +724,7 @@ predefined_build() {
 			all_locales=0
 			library=0
 			fuzz=0
+			ossfuzz=0
 			time_tests=0
 			vg=0
 			memcheck=0
@@ -755,6 +758,7 @@ predefined_build() {
 			all_locales=0
 			library=0
 			fuzz=0
+			ossfuzz=0
 			time_tests=0
 			vg=0
 			memcheck=0
@@ -772,7 +776,8 @@ predefined_build() {
 			dc_default_digit_clamp=0;;
 
 		GDH)
-			CFLAGS="-flto -Weverything -Wno-padded -Wno-unsafe-buffer-usage -Wno-poison-system-directories -Werror -pedantic -std=c11"
+			CFLAGS="-Weverything -Wno-padded -Wno-unsafe-buffer-usage -Wno-poison-system-directories"
+			CFLAGS="$CFLAGS -Wno-switch-default -Werror -pedantic -std=c11"
 			bc_only=0
 			dc_only=0
 			coverage=0
@@ -789,6 +794,7 @@ predefined_build() {
 			all_locales=0
 			library=0
 			fuzz=0
+			ossfuzz=0
 			time_tests=0
 			vg=0
 			memcheck=0
@@ -806,7 +812,8 @@ predefined_build() {
 			dc_default_digit_clamp=1;;
 
 		DBG)
-			CFLAGS="-Weverything -Wno-padded -Wno-unsafe-buffer-usage -Wno-poison-system-directories -Werror -pedantic -std=c11"
+			CFLAGS="-Weverything -Wno-padded -Wno-unsafe-buffer-usage -Wno-poison-system-directories"
+			CFLAGS="$CFLAGS -Wno-switch-default -Werror -pedantic -std=c11"
 			bc_only=0
 			dc_only=0
 			coverage=0
@@ -823,6 +830,7 @@ predefined_build() {
 			all_locales=0
 			library=0
 			fuzz=0
+			ossfuzz=0
 			time_tests=0
 			vg=0
 			memcheck=1
@@ -888,6 +896,7 @@ strip_bin=1
 all_locales=0
 library=0
 fuzz=0
+ossfuzz=0
 time_tests=0
 vg=0
 memcheck=0
@@ -911,7 +920,7 @@ dc_default_digit_clamp=0
 # getopts is a POSIX utility, but it cannot handle long options. Thus, the
 # handling of long options is done by hand, and that's the reason that short and
 # long options cannot be mixed.
-while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvz-" opt; do
+while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvzZ-" opt; do
 
 	case "$opt" in
 		a) library=1 ;;
@@ -944,6 +953,7 @@ while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvz-" opt; do
 		T) strip_bin=0 ;;
 		v) vg=1 ;;
 		z) fuzz=1 ;;
+		Z) ossfuzz=1 ;;
 		-)
 			arg="$1"
 			arg="${arg#--}"
@@ -1070,6 +1080,7 @@ while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvz-" opt; do
 				enable-test-timing) time_tests=1 ;;
 				enable-valgrind) vg=1 ;;
 				enable-fuzz-mode) fuzz=1 ;;
+				enable-ossfuzz-mode) ossfuzz=1 ;;
 				enable-memcheck) memcheck=1 ;;
 				install-all-locales) all_locales=1 ;;
 				help* | bc-only* | dc-only* | coverage* | debug*)
@@ -1320,6 +1331,45 @@ elif [ "$dc_only" -eq 1 ]; then
 
 	tests="test_dc"
 
+elif [ "$ossfuzz" -eq 1 ]; then
+
+	if [ "$bc_only" -ne 0 ] || [ "$dc_only" -ne 0 ]; then
+		usage "An OSS-Fuzz build must build both fuzzers."
+	fi
+
+	bc=1
+	dc=1
+
+	# Expressions *cannot* exit in an OSS-Fuzz build.
+	bc_default_expr_exit=0
+	dc_default_expr_exit=0
+
+	executables="bc_fuzzer and dc_fuzzer"
+
+	karatsuba="@\$(KARATSUBA) 30 0 \$(BC_EXEC)"
+	karatsuba_test="@\$(KARATSUBA) 1 100 \$(BC_EXEC)"
+
+	if [ "$library" -eq 0 ]; then
+		install_prereqs=" install_execs"
+		install_man_prereqs=" install_bc_manpage install_dc_manpage"
+		uninstall_prereqs=" uninstall_bc uninstall_dc"
+		uninstall_man_prereqs=" uninstall_bc_manpage uninstall_dc_manpage"
+	else
+		install_prereqs=" install_library install_bcl_header"
+		install_man_prereqs=" install_bcl_manpage"
+		uninstall_prereqs=" uninstall_library uninstall_bcl_header"
+		uninstall_man_prereqs=" uninstall_bcl_manpage"
+		tests="test_library"
+	fi
+
+	second_target_prereqs="src/bc_fuzzer.o $default_target_prereqs"
+	default_target_prereqs="\$(BC_FUZZER) src/dc_fuzzer.o $default_target_prereqs"
+	default_target_cmd="\$(CXX) \$(CFLAGS) src/dc_fuzzer.o \$(LIB_FUZZING_ENGINE) \$(OBJS) \$(LDFLAGS) -o \$(DC_FUZZER) \&\& ln -sf ./dc_fuzzer_c \$(DC_FUZZER_C)"
+	second_target_cmd="\$(CXX) \$(CFLAGS) src/bc_fuzzer.o \$(LIB_FUZZING_ENGINE) \$(OBJS) \$(LDFLAGS) -o \$(BC_FUZZER) \&\& ln -sf ./bc_fuzzer_c \$(BC_FUZZER_C)"
+
+	default_target="\$(DC_FUZZER) \$(DC_FUZZER_C)"
+	second_target="\$(BC_FUZZER) \$(BC_FUZZER_C)"
+
 else
 
 	bc=1
@@ -1349,8 +1399,12 @@ else
 
 fi
 
+if [ "$fuzz" -ne 0 ] && [ "$ossfuzz" -ne 0 ]; then
+	usage "Fuzzing mode and OSS-Fuzz mode are mutually exclusive"
+fi
+
 # We need specific stuff for fuzzing.
-if [ "$fuzz" -ne 0 ]; then
+if [ "$fuzz" -ne 0 ] || [ "$ossfuzz" -ne 0 ]; then
 	debug=1
 	hist=0
 	nls=0
@@ -1395,7 +1449,6 @@ else
 	COVERAGE_PREREQS=""
 fi
 
-
 # Set some defaults.
 if [ -z "${DESTDIR+set}" ]; then
 	destdir=""
@@ -1485,8 +1538,8 @@ if [ "$nls" -ne 0 ]; then
 
 	flags="-DBC_ENABLE_NLS=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
 	flags="$flags -DBC_ENABLE_HISTORY=$hist -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
-	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
-	flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
+	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -DBC_ENABLE_OSSFUZZ=0"
+	flags="$flags -I$scriptdir/include/ -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
 
 	ccbase=$(basename "$CC")
 
@@ -1494,14 +1547,14 @@ if [ "$nls" -ne 0 ]; then
 		flags="$flags -Wno-unreachable-code"
 	fi
 
-	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -o "./vm.o" > /dev/null 2>&1
+	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -E > /dev/null
 
 	err="$?"
 
 	rm -rf "./vm.o"
 
-	# If this errors, it is probably because of building on Windows,
-	# and NLS is not supported on Windows, so disable it.
+	# If this errors, it is probably because of building on Windows or musl,
+	# and NLS is not supported on Windows or musl, so disable it.
 	if [ "$err" -ne 0 ]; then
 		printf 'NLS does not work.\n'
 		if [ $force -eq 0 ]; then
@@ -1514,7 +1567,7 @@ if [ "$nls" -ne 0 ]; then
 		printf 'NLS works.\n\n'
 
 		printf 'Testing gencat...\n'
-		gencat "./en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null 2>&1
+		gencat "./en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null
 
 		err="$?"
 
@@ -1587,10 +1640,10 @@ if [ "$hist" -eq 1 ]; then
 	flags="-DBC_ENABLE_HISTORY=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
 	flags="$flags -DBC_ENABLE_NLS=$nls -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
 	flags="$flags -DBC_ENABLE_EDITLINE=$editline -DBC_ENABLE_READLINE=$readline"
-	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
-	flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
+	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -DBC_ENABLE_OSSFUZZ=0"
+	flags="$flags -I$scriptdir/include/ -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
 
-	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/history.c" -o "./history.o" > /dev/null 2>&1
+	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/history.c" -E > /dev/null
 
 	err="$?"
 
@@ -1660,7 +1713,7 @@ set +e
 printf 'Testing for FreeBSD...\n'
 
 flags="-DBC_TEST_FREEBSD -DBC_ENABLE_AFL=0"
-"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
+"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/scripts/os.c" > /dev/null
 
 err="$?"
 
@@ -1677,7 +1730,7 @@ fi
 printf 'Testing for macOS...\n'
 
 flags="-DBC_TEST_APPLE -DBC_ENABLE_AFL=0"
-"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
+"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/scripts/os.c" > /dev/null
 
 err="$?"
 
@@ -1705,7 +1758,7 @@ fi
 printf 'Testing for OpenBSD...\n'
 
 flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0"
-"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
+"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/scripts/os.c" > /dev/null
 
 err="$?"
 
@@ -1741,7 +1794,7 @@ GEN_DIR="$scriptdir/gen"
 # These lines set the appropriate targets based on whether `gen/strgen.c` or
 # `gen/strgen.sh` is used.
 GEN="strgen"
-GEN_EXEC_TARGET="\$(HOSTCC) -DBC_ENABLE_AFL=0 -I$scriptdir/include/  \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
+GEN_EXEC_TARGET="\$(HOSTCC) -DBC_ENABLE_AFL=0 -DBC_ENABLE_OSSFUZZ=0 -I$scriptdir/include/ \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
 CLEAN_PREREQS=" clean_gen clean_coverage"
 
 if [ -z "${GEN_HOST+set}" ]; then
@@ -1754,8 +1807,9 @@ else
 	fi
 fi
 
+# The fuzzer files are always unneeded because they'll be built separately.
 manpage_args=""
-unneeded=""
+unneeded="bc_fuzzer.c dc_fuzzer.c"
 headers="\$(HEADERS)"
 
 # This series of if statements figure out what source files are *not* needed.
@@ -1826,6 +1880,14 @@ if [ "$library" -ne 0 ]; then
 
 	fi
 
+elif [ "$ossfuzz" -ne 0 ]; then
+
+	unneeded="$unneeded library.c main.c"
+
+	PC_PATH=""
+	pkg_config_install=""
+	pkg_config_uninstall=""
+
 else
 
 	unneeded="$unneeded library.c"
@@ -1836,9 +1898,10 @@ else
 
 fi
 
-# library.c is not needed under normal circumstances.
+# library.c, bc_fuzzer.c, and dc_fuzzer.c are not needed under normal
+# circumstances.
 if [ "$unneeded" = "" ]; then
-	unneeded="library.c"
+	unneeded="library.c bc_fuzzer.c dc_fuzzer.c"
 fi
 
 # This sets the appropriate manpage for a full build.
@@ -1846,7 +1909,7 @@ if [ "$manpage_args" = "" ]; then
 	manpage_args="A"
 fi
 
-if [ "$vg" -ne 0 ]; then
+if [ "$vg" -ne 0 ] || [ "$ossfuzz" -ne 0 ]; then
 	memcheck=1
 fi
 
@@ -2011,7 +2074,9 @@ contents=$(replace "$contents" "HISTORY" "$hist")
 contents=$(replace "$contents" "EXTRA_MATH" "$extra_math")
 contents=$(replace "$contents" "NLS" "$nls")
 contents=$(replace "$contents" "FUZZ" "$fuzz")
+contents=$(replace "$contents" "OSSFUZZ" "$ossfuzz")
 contents=$(replace "$contents" "MEMCHECK" "$memcheck")
+contents=$(replace "$contents" "LIB_FUZZING_ENGINE" "$LIB_FUZZING_ENGINE")
 
 contents=$(replace "$contents" "BC_LIB_O" "$bc_lib")
 contents=$(replace "$contents" "BC_HELP_O" "$bc_help")
@@ -2117,6 +2182,15 @@ if [ "$dc" -ne 0 ]; then
 	gen_err_tests dc $dc_test_exec
 fi
 
+if [ "$ossfuzz" -ne 0 ]; then
+
+	printf 'bc_fuzzer_c: $(BC_FUZZER)\n\tln -sf $(BC_FUZZER) bc_fuzzer_c\n' >> Makefile
+	printf 'bc_fuzzer_C: $(BC_FUZZER)\n\tln -sf $(BC_FUZZER) bc_fuzzer_C\n' >> Makefile
+	printf 'dc_fuzzer_c: $(DC_FUZZER)\n\tln -sf $(DC_FUZZER) dc_fuzzer_c\n' >> Makefile
+	printf 'dc_fuzzer_C: $(DC_FUZZER)\n\tln -sf $(DC_FUZZER) dc_fuzzer_C\n' >> Makefile
+
+fi
+
 # Copy the correct manuals to the expected places.
 mkdir -p manuals
 cp -f "$scriptdir/manuals/bc/$manpage_args.1.md" manuals/bc.1.md
diff --git a/contrib/bc/include/args.h b/contrib/bc/include/args.h
index f1e9f007bddf..8f8f00be4630 100644
--- a/contrib/bc/include/args.h
+++ b/contrib/bc/include/args.h
@@ -54,7 +54,7 @@
  *                    any.
  */
 void
-bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig* scale,
+bc_args(int argc, const char* argv[], bool exit_exprs, BcBigDig* scale,
         BcBigDig* ibase, BcBigDig* obase);
 
 #if BC_ENABLED
diff --git a/contrib/bc/include/bc.h b/contrib/bc/include/bc.h
index b25df09a174e..2213278be1da 100644
--- a/contrib/bc/include/bc.h
+++ b/contrib/bc/include/bc.h
@@ -51,7 +51,7 @@
  * @return  A status.
  */
 BcStatus
-bc_main(int argc, char* argv[]);
+bc_main(int argc, const char* argv[]);
 
 // These are references to the help text, the library text, and the "filename"
 // for the library.
diff --git a/contrib/bc/include/dc.h b/contrib/bc/include/dc.h
index 1328f1c63b38..63f5ccbd10e3 100644
--- a/contrib/bc/include/dc.h
+++ b/contrib/bc/include/dc.h
@@ -48,7 +48,7 @@
  * @return  A status.
  */
 BcStatus
-dc_main(int argc, char* argv[]);
+dc_main(int argc, const char* argv[]);
 
 // A reference to the dc help text.
 extern const char dc_help[];
diff --git a/contrib/bc/include/opt.h b/contrib/bc/include/opt.h
index e60328994d8c..41058cb4e29c 100644
--- a/contrib/bc/include/opt.h
+++ b/contrib/bc/include/opt.h
@@ -47,7 +47,7 @@
 typedef struct BcOpt
 {
 	/// The array of arguments.
-	char** argv;
+	const char** argv;
 
 	/// The index of the current argument.
 	size_t optind;
@@ -59,7 +59,7 @@ typedef struct BcOpt
 	int subopt;
 
 	/// The option argument.
-	char* optarg;
+	const char* optarg;
 
 } BcOpt;
 
@@ -103,7 +103,7 @@ typedef struct BcOptLong
  * @param argv  The array of arguments.
  */
 void
-bc_opt_init(BcOpt* o, char** argv);
+bc_opt_init(BcOpt* o, const char** argv);
 
 /**
  * Parse an option. This returns a value the same way getopt() and getopt_long()
diff --git a/contrib/bc/include/ossfuzz.h b/contrib/bc/include/ossfuzz.h
new file mode 100644
index 000000000000..5c12a3c9c9fb
--- /dev/null
+++ b/contrib/bc/include/ossfuzz.h
@@ -0,0 +1,79 @@
+/*
+ * *****************************************************************************
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * *****************************************************************************
+ *
+ * Declarations for the OSS-Fuzz build of bc and dc.
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef BC_OSSFUZZ_H
+#define BC_OSSFUZZ_H
+
+/// The number of args in fuzzer arguments, including the NULL terminator.
+extern const size_t bc_fuzzer_args_len;
+
+/// The standard arguments for the bc fuzzer with the -c argument.
+extern const char* bc_fuzzer_args_c[];
+
+/// The standard arguments for the bc fuzzer with the -C argument.
+extern const char* bc_fuzzer_args_C[];
+
+/// The standard arguments for the dc fuzzer with the -c argument.
+extern const char* dc_fuzzer_args_c[];
+
+/// The standard arguments for the dc fuzzer with the -C argument.
+extern const char* dc_fuzzer_args_C[];
+
+/// The data pointer.
+extern uint8_t* bc_fuzzer_data;
+
+/**
+ * The function that the fuzzer runs.
+ * @param Data  The data.
+ * @param Size  The number of bytes in @a Data.
+ * @return      0 on success, -1 on error.
+ * @pre         @a Data must not be equal to NULL if @a Size > 0.
+ */
+int
+LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size);
+
+/**
+ * The initialization function for the fuzzer.
+ * @param argc  A pointer to the argument count.
+ * @param argv  A pointer to the argument list.
+ * @return      0 on success, -1 on error.
+ */
+int
+LLVMFuzzerInitialize(int* argc, char*** argv);
+
+#endif // BC_OSSFUZZ_H
diff --git a/contrib/bc/include/status.h b/contrib/bc/include/status.h
index f579df8c649b..203f09af628b 100644
--- a/contrib/bc/include/status.h
+++ b/contrib/bc/include/status.h
@@ -46,27 +46,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-// This is used by configure.sh to test for OpenBSD.
-#ifdef BC_TEST_OPENBSD
-#ifdef __OpenBSD__
-#error On OpenBSD without _BSD_SOURCE
-#endif // __OpenBSD__
-#endif // BC_TEST_OPENBSD
-
-// This is used by configure.sh to test for FreeBSD.
-#ifdef BC_TEST_FREEBSD
-#ifdef __FreeBSD__
-#error On FreeBSD with _POSIX_C_SOURCE
-#endif // __FreeBSD__
-#endif // BC_TEST_FREEBSD
-
-// This is used by configure.sh to test for macOS.
-#ifdef BC_TEST_APPLE
-#ifdef __APPLE__
-#error On macOS without _DARWIN_C_SOURCE
-#endif // __APPLE__
-#endif // BC_TEST_APPLE
-
 // Windows has deprecated isatty() and the rest of these. Or doesn't have them.
 // So these are just fixes for Windows.
 #ifdef _WIN32
@@ -676,9 +655,13 @@ typedef enum BcMode
 	/// File mode.
 	BC_MODE_FILE,
 
+#if !BC_ENABLE_OSSFUZZ
+
 	/// stdin mode.
 	BC_MODE_STDIN,
 
+#endif // !BC_ENABLE_OSSFUZZ
+
 } BcMode;
 
 /// Do a longjmp(). This is what to use when activating an "exception", i.e., a
diff --git a/contrib/bc/include/version.h b/contrib/bc/include/version.h
index 586691a6e7ef..897a19530e3f 100644
--- a/contrib/bc/include/version.h
+++ b/contrib/bc/include/version.h
@@ -37,6 +37,6 @@
 #define BC_VERSION_H
 
 /// The current version.
-#define VERSION 6.7.6
+#define VERSION 7.0.0
 
 #endif // BC_VERSION_H
diff --git a/contrib/bc/include/vm.h b/contrib/bc/include/vm.h
index 052c1d14c237..e81206b63871 100644
--- a/contrib/bc/include/vm.h
+++ b/contrib/bc/include/vm.h
@@ -794,7 +794,7 @@ bc_vm_info(const char* const help);
  * @return      A status.
  */
 BcStatus
-bc_vm_boot(int argc, char* argv[]);
+bc_vm_boot(int argc, const char* argv[]);
 
 /**
  * Initializes some of the BcVm global. This is separate to make things easier
diff --git a/contrib/bc/manuals/dc/A.1 b/contrib/bc/manuals/dc/A.1
index 33ecb8e2031e..d59e0fa68a58 100644
--- a/contrib/bc/manuals/dc/A.1
+++ b/contrib/bc/manuals/dc/A.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1275,11 +1275,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
 First, any macros that are executing are stopped and popped off the
-stack.
+execution stack.
 The behavior is not unlike that of exceptions in programming languages.
 Then the execution point is set so that any code waiting to execute
 (after all macros returned) is skipped.
 .PP
+However, the stack of values is \f[I]not\f[R] cleared; in interactive
+mode, users can inspect the stack and manipulate it.
+.PP
 Thus, when dc(1) resets, it skips any remaining code waiting to be
 executed.
 Then, if it is interactive mode, and the error was not a fatal error
diff --git a/contrib/bc/manuals/dc/A.1.md b/contrib/bc/manuals/dc/A.1.md
index 613f98f76814..ad0c59934fd1 100644
--- a/contrib/bc/manuals/dc/A.1.md
+++ b/contrib/bc/manuals/dc/A.1.md
@@ -1130,11 +1130,14 @@ the next non-space characters do not match that regex.
 When dc(1) encounters an error or a signal that it has a non-default handler
 for, it resets. This means that several things happen.
 
-First, any macros that are executing are stopped and popped off the stack.
-The behavior is not unlike that of exceptions in programming languages. Then
-the execution point is set so that any code waiting to execute (after all
+First, any macros that are executing are stopped and popped off the execution
+stack. The behavior is not unlike that of exceptions in programming languages.
+Then the execution point is set so that any code waiting to execute (after all
 macros returned) is skipped.
 
+However, the stack of values is *not* cleared; in interactive mode, users can
+inspect the stack and manipulate it.
+
 Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
 Then, if it is interactive mode, and the error was not a fatal error (see the
 **EXIT STATUS** section), it asks for more input; otherwise, it exits with the
diff --git a/contrib/bc/manuals/dc/E.1 b/contrib/bc/manuals/dc/E.1
index 91f68dfd7467..a5febe44705f 100644
--- a/contrib/bc/manuals/dc/E.1
+++ b/contrib/bc/manuals/dc/E.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1061,11 +1061,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
 First, any macros that are executing are stopped and popped off the
-stack.
+execution stack.
 The behavior is not unlike that of exceptions in programming languages.
 Then the execution point is set so that any code waiting to execute
 (after all macros returned) is skipped.
 .PP
+However, the stack of values is \f[I]not\f[R] cleared; in interactive
+mode, users can inspect the stack and manipulate it.
+.PP
 Thus, when dc(1) resets, it skips any remaining code waiting to be
 executed.
 Then, if it is interactive mode, and the error was not a fatal error
diff --git a/contrib/bc/manuals/dc/E.1.md b/contrib/bc/manuals/dc/E.1.md
index 3a47f789bd3e..54b877999d0d 100644
--- a/contrib/bc/manuals/dc/E.1.md
+++ b/contrib/bc/manuals/dc/E.1.md
@@ -961,11 +961,14 @@ the next non-space characters do not match that regex.
 When dc(1) encounters an error or a signal that it has a non-default handler
 for, it resets. This means that several things happen.
 
-First, any macros that are executing are stopped and popped off the stack.
-The behavior is not unlike that of exceptions in programming languages. Then
-the execution point is set so that any code waiting to execute (after all
+First, any macros that are executing are stopped and popped off the execution
+stack. The behavior is not unlike that of exceptions in programming languages.
+Then the execution point is set so that any code waiting to execute (after all
 macros returned) is skipped.
 
+However, the stack of values is *not* cleared; in interactive mode, users can
+inspect the stack and manipulate it.
+
 Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
 Then, if it is interactive mode, and the error was not a fatal error (see the
 **EXIT STATUS** section), it asks for more input; otherwise, it exits with the
diff --git a/contrib/bc/manuals/dc/EH.1 b/contrib/bc/manuals/dc/EH.1
index e60e6e0d8497..61fbaa4efe92 100644
--- a/contrib/bc/manuals/dc/EH.1
+++ b/contrib/bc/manuals/dc/EH.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1061,11 +1061,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
 First, any macros that are executing are stopped and popped off the
-stack.
+execution stack.
 The behavior is not unlike that of exceptions in programming languages.
 Then the execution point is set so that any code waiting to execute
 (after all macros returned) is skipped.
 .PP
+However, the stack of values is \f[I]not\f[R] cleared; in interactive
+mode, users can inspect the stack and manipulate it.
+.PP
 Thus, when dc(1) resets, it skips any remaining code waiting to be
 executed.
 Then, if it is interactive mode, and the error was not a fatal error
diff --git a/contrib/bc/manuals/dc/EH.1.md b/contrib/bc/manuals/dc/EH.1.md
index 761b9a89947b..6398477a84dd 100644
--- a/contrib/bc/manuals/dc/EH.1.md
+++ b/contrib/bc/manuals/dc/EH.1.md
@@ -961,11 +961,14 @@ the next non-space characters do not match that regex.
 When dc(1) encounters an error or a signal that it has a non-default handler
 for, it resets. This means that several things happen.
 
-First, any macros that are executing are stopped and popped off the stack.
-The behavior is not unlike that of exceptions in programming languages. Then
-the execution point is set so that any code waiting to execute (after all
+First, any macros that are executing are stopped and popped off the execution
+stack. The behavior is not unlike that of exceptions in programming languages.
+Then the execution point is set so that any code waiting to execute (after all
 macros returned) is skipped.
 
+However, the stack of values is *not* cleared; in interactive mode, users can
+inspect the stack and manipulate it.
+
 Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
 Then, if it is interactive mode, and the error was not a fatal error (see the
 **EXIT STATUS** section), it asks for more input; otherwise, it exits with the
diff --git a/contrib/bc/manuals/dc/EHN.1 b/contrib/bc/manuals/dc/EHN.1
index d26d49c5ce3d..974cb3c86791 100644
--- a/contrib/bc/manuals/dc/EHN.1
+++ b/contrib/bc/manuals/dc/EHN.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1061,11 +1061,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
 First, any macros that are executing are stopped and popped off the
-stack.
+execution stack.
 The behavior is not unlike that of exceptions in programming languages.
 Then the execution point is set so that any code waiting to execute
 (after all macros returned) is skipped.
 .PP
+However, the stack of values is \f[I]not\f[R] cleared; in interactive
+mode, users can inspect the stack and manipulate it.
+.PP
 Thus, when dc(1) resets, it skips any remaining code waiting to be
 executed.
 Then, if it is interactive mode, and the error was not a fatal error
diff --git a/contrib/bc/manuals/dc/EHN.1.md b/contrib/bc/manuals/dc/EHN.1.md
index 58ae149bb686..51e30849996e 100644
--- a/contrib/bc/manuals/dc/EHN.1.md
+++ b/contrib/bc/manuals/dc/EHN.1.md
@@ -961,11 +961,14 @@ the next non-space characters do not match that regex.
 When dc(1) encounters an error or a signal that it has a non-default handler
 for, it resets. This means that several things happen.
 
-First, any macros that are executing are stopped and popped off the stack.
-The behavior is not unlike that of exceptions in programming languages. Then
-the execution point is set so that any code waiting to execute (after all
+First, any macros that are executing are stopped and popped off the execution
+stack. The behavior is not unlike that of exceptions in programming languages.
+Then the execution point is set so that any code waiting to execute (after all
 macros returned) is skipped.
 
+However, the stack of values is *not* cleared; in interactive mode, users can
+inspect the stack and manipulate it.
+
 Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
 Then, if it is interactive mode, and the error was not a fatal error (see the
 **EXIT STATUS** section), it asks for more input; otherwise, it exits with the
diff --git a/contrib/bc/manuals/dc/EN.1 b/contrib/bc/manuals/dc/EN.1
index 03cb5743602c..5ce8defc91c7 100644
--- a/contrib/bc/manuals/dc/EN.1
+++ b/contrib/bc/manuals/dc/EN.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1061,11 +1061,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
 First, any macros that are executing are stopped and popped off the
-stack.
+execution stack.
 The behavior is not unlike that of exceptions in programming languages.
 Then the execution point is set so that any code waiting to execute
 (after all macros returned) is skipped.
 .PP
+However, the stack of values is \f[I]not\f[R] cleared; in interactive
+mode, users can inspect the stack and manipulate it.
+.PP
 Thus, when dc(1) resets, it skips any remaining code waiting to be
 executed.
 Then, if it is interactive mode, and the error was not a fatal error
diff --git a/contrib/bc/manuals/dc/EN.1.md b/contrib/bc/manuals/dc/EN.1.md
index 64c945be8857..ab9647a196be 100644
--- a/contrib/bc/manuals/dc/EN.1.md
+++ b/contrib/bc/manuals/dc/EN.1.md
@@ -961,11 +961,14 @@ the next non-space characters do not match that regex.
 When dc(1) encounters an error or a signal that it has a non-default handler
 for, it resets. This means that several things happen.
 
-First, any macros that are executing are stopped and popped off the stack.
-The behavior is not unlike that of exceptions in programming languages. Then
-the execution point is set so that any code waiting to execute (after all
+First, any macros that are executing are stopped and popped off the execution
+stack. The behavior is not unlike that of exceptions in programming languages.
+Then the execution point is set so that any code waiting to execute (after all
 macros returned) is skipped.
 
+However, the stack of values is *not* cleared; in interactive mode, users can
+inspect the stack and manipulate it.
+
 Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
 Then, if it is interactive mode, and the error was not a fatal error (see the
 **EXIT STATUS** section), it asks for more input; otherwise, it exits with the
diff --git a/contrib/bc/manuals/dc/H.1 b/contrib/bc/manuals/dc/H.1
index 36f7458a3316..82c1bbd5c2b9 100644
--- a/contrib/bc/manuals/dc/H.1
+++ b/contrib/bc/manuals/dc/H.1
@@ -25,7 +25,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "DC" "1" "January 2024" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2024" "Gavin D. Howard" "General Commands Manual"
 .nh
 .ad l
 .SH Name
@@ -1275,11 +1275,14 @@ handler for, it resets.
 This means that several things happen.
 .PP
*** 1272 LINES SKIPPED ***