git: cde51c2590cc - stable/13 - contrib/bc: MFC version 5.2.2

From: Stefan Eßer <se_at_FreeBSD.org>
Date: Fri, 04 Mar 2022 20:20:16 UTC
The branch stable/13 has been updated by se:

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

commit cde51c2590cc2653c4658410142563d3a4298927
Author:     Stefan Eßer <se@FreeBSD.org>
AuthorDate: 2022-02-05 21:26:36 +0000
Commit:     Stefan Eßer <se@FreeBSD.org>
CommitDate: 2022-03-04 20:19:50 +0000

    contrib/bc: MFC version 5.2.2
    
    This release assigns a default value to the internal program name
    variable in case the program is invoked with argv[0] == NULL.
    
    There was no security issue: the prevuous program version would have
    been immediately terminated due to a NULL dereference.
    
    (cherry picked from commit 00698711dee1d990d3db9c41bf58394e589eecfe)
---
 contrib/bc/NEWS.md           |  8 ++++++++
 contrib/bc/configure.sh      |  6 +++---
 contrib/bc/include/lang.h    |  8 ++++++++
 contrib/bc/include/version.h |  2 +-
 contrib/bc/include/vm.h      |  2 ++
 contrib/bc/src/main.c        | 28 ++++++++++++++++++++++++----
 contrib/bc/src/program.c     |  1 -
 7 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/contrib/bc/NEWS.md b/contrib/bc/NEWS.md
index 5d0126b821a8..9a354e537d9f 100644
--- a/contrib/bc/NEWS.md
+++ b/contrib/bc/NEWS.md
@@ -1,5 +1,13 @@
 # News
 
+## 5.2.2
+
+This is a production release that fixes one bug, a segmentation fault if
+`argv[0]` equals `NULL`.
+
+This is not a critical bug; there will be no vulnerability as far as I can tell.
+There is no need to update if you do not wish to.
+
 ## 5.2.1
 
 This is a production release that fixes two parse bugs when in POSIX standard
diff --git a/contrib/bc/configure.sh b/contrib/bc/configure.sh
index 76ffb2b9a18e..fc66ffc51066 100755
--- a/contrib/bc/configure.sh
+++ b/contrib/bc/configure.sh
@@ -36,7 +36,7 @@ builddir=$(pwd)
 . "$scriptdir/scripts/functions.sh"
 
 # Simply prints the help message and quits based on the argument.
-# @param val  The value to pass to exit. Must be an integer.
+# @param msg  The help message to print.
 usage() {
 
 	if [ $# -gt 0 ]; then
@@ -95,7 +95,7 @@ usage() {
 	printf '    -f, --force\n'
 	printf '        Force use of all enabled options, even if they do not work. This\n'
 	printf '        option is to allow the maintainer a way to test that certain options\n'
-	printf '        are not failing invisibly. (Development only.)'
+	printf '        are not failing invisibly. (Development only.)\n'
 	printf '    -g, --debug\n'
 	printf '        Build in debug mode. Adds the "-g" flag, and if there are no\n'
 	printf '        other CFLAGS, and "-O" was not given, this also adds the "-O0"\n'
@@ -535,7 +535,7 @@ gen_std_test_targets() {
 # This allows `make test_bc_errors` and `make test_dc_errors` to run in
 # parallel.
 #
-# @param name        Which calculator to generate tests for.
+# @param name  Which calculator to generate tests for.
 gen_err_tests() {
 
 	_gen_err_tests_name="$1"
diff --git a/contrib/bc/include/lang.h b/contrib/bc/include/lang.h
index 705aca35df1c..09b0d6072806 100644
--- a/contrib/bc/include/lang.h
+++ b/contrib/bc/include/lang.h
@@ -37,6 +37,9 @@
 #define BC_LANG_H
 
 #include <stdbool.h>
+#if BC_C11
+#include <assert.h>
+#endif // BC_C11
 
 #include <status.h>
 #include <vector.h>
@@ -324,6 +327,11 @@ typedef enum BcInst {
 
 } BcInst;
 
+#if BC_C11
+static_assert(BC_INST_INVALID <= UCHAR_MAX,
+              "Too many instructions to fit into an unsigned char");
+#endif // BC_C11
+
 /// Used by maps to identify where items are in the array.
 typedef struct BcId {
 
diff --git a/contrib/bc/include/version.h b/contrib/bc/include/version.h
index eca73baf508f..0c4122528e7d 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 5.2.1
+#define VERSION 5.2.2
 
 #endif // BC_VERSION_H
diff --git a/contrib/bc/include/vm.h b/contrib/bc/include/vm.h
index d6f698fb1e6d..6f69712a804b 100644
--- a/contrib/bc/include/vm.h
+++ b/contrib/bc/include/vm.h
@@ -545,8 +545,10 @@ typedef struct BcVm {
 	/// The messages for each error.
 	const char *err_msgs[BC_ERR_NELEMS];
 
+#if BC_ENABLE_NLS
 	/// The locale.
 	const char *locale;
+#endif // BC_ENABLE_NLS
 
 #endif // !BC_ENABLE_LIBRARY
 
diff --git a/contrib/bc/src/main.c b/contrib/bc/src/main.c
index 38c87a415f2b..3146f983787e 100644
--- a/contrib/bc/src/main.c
+++ b/contrib/bc/src/main.c
@@ -37,7 +37,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if BC_ENABLE_NLS
 #include <locale.h>
+#endif // BC_ENABLE_NLS
 
 #ifndef _WIN32
 #include <libgen.h>
@@ -56,16 +58,34 @@ int main(int argc, char *argv[]) {
 	char *name;
 	size_t len = strlen(BC_EXECPREFIX);
 
+#if BC_ENABLE_NLS
 	// Must set the locale properly in order to have the right error messages.
 	vm.locale = setlocale(LC_ALL, "");
+#endif // BC_ENABLE_NLS
 
 	// Set the start pledge().
 	bc_pledge(bc_pledge_start, NULL);
 
-	// Figure out the name of the calculator we are using. We can't use basename
-	// because it's not portable, but yes, this is stripping off the directory.
-	name = strrchr(argv[0], BC_FILE_SEP);
-	vm.name = (name == NULL) ? argv[0] : name + 1;
+	// Sometimes, argv[0] can be NULL. Better make sure to be robust against it.
+	if (argv[0] != NULL) {
+
+		// Figure out the name of the calculator we are using. We can't use
+		// basename because it's not portable, but yes, this is stripping off
+		// the directory.
+		name = strrchr(argv[0], BC_FILE_SEP);
+		vm.name = (name == NULL) ? argv[0] : name + 1;
+	}
+	else
+	{
+#if !DC_ENABLED
+		vm.name = "bc";
+#elif !BC_ENABLED
+		vm.name = "dc";
+#else
+		// Just default to bc in that case.
+		vm.name = "bc";
+#endif
+	}
 
 	// If the name is longer than the length of the prefix, skip the prefix.
 	if (strlen(vm.name) > len) vm.name += len;
diff --git a/contrib/bc/src/program.c b/contrib/bc/src/program.c
index bc5b88011638..8ec1a011a26d 100644
--- a/contrib/bc/src/program.c
+++ b/contrib/bc/src/program.c
@@ -2718,7 +2718,6 @@ void bc_program_exec(BcProgram *p) {
 	while (ip->idx < func->code.len)
 #endif // !BC_HAS_COMPUTED_GOTO
 	{
-
 		BC_SIG_ASSERT_NOT_LOCKED;
 
 #if BC_HAS_COMPUTED_GOTO