From: George Koehler Subject: lang/gbc write overflow To: ports@openbsd.org Cc: Ivan Ivanov Date: Wed, 27 Mar 2024 19:04:28 -0400 Here's a diff to fix GNU bc 1.07.1 in OpenBSD ports. Wrong code in bc/scan.c was using (yy_size_t *)&result to write to an int. This was an overflow on LP64_ARCHS, by writing 8 bytes to a 4-byte int. The problem was more obvious when big-endian. If we would read 51 bytes, - a little-endian amd64 would write (int []){51, 0}, so result = 51 was correct, but the extra 0 clobbered 4 bytes of other memory. - my big-endian powerpc64 wrote (int []){0, 51}, so result = 0 caused an early end of file. This broke my powerpc64 build when bc tried to compile its math library, but the compiled code was empty. The new patch does "result = ...", so the C compiler writes the correct size. Now my powerpc64 can package and run gbc. The patch causes flex(1) to remake scan.c from scan.l. OpenBSD's flex changes result from int to yy_size_t, but "result = ..." should work with either type. (When I tried (int *)&result, I built a broken bc that wrote 4 bytes to an 8-byte size.) Also delete BROKEN-sparc64, but I don't have a sparc64. I suspect that (yy_size_t *)&result was not a multiple of 8 and raised a SIGBUS for misalignment on sparc64, but I don't know. ok? Index: Makefile =================================================================== RCS file: /cvs/ports/math/gbc/Makefile,v diff -u -p -r1.6 Makefile --- Makefile 27 Sep 2023 09:27:54 -0000 1.6 +++ Makefile 27 Mar 2024 22:04:45 -0000 @@ -1,9 +1,7 @@ -BROKEN-sparc64 = Bus error during build - COMMENT = GNU version of the arbitrary precision calculators bc and dc DISTNAME = bc-1.07.1 PKGNAME = g${DISTNAME} -REVISION = 0 +REVISION = 1 CATEGORIES = math HOMEPAGE = https://www.gnu.org/software/bc/ Index: patches/patch-bc_scan_l =================================================================== RCS file: patches/patch-bc_scan_l diff -N patches/patch-bc_scan_l --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-bc_scan_l 27 Mar 2024 22:04:45 -0000 @@ -0,0 +1,74 @@ +The cast (yy_size_t *)&result was wrong, because result was an int in +upstream's flex; this caused an overflow on LP64_ARCHS (by writing 8 +bytes to a 4-byte int), which broke the build on powerpc64. + +This patch causes the build to run flex(1), overwriting scan.c from +upstream. OpenBSD's flex changes result from int to yy_size_t. + +Index: bc/scan.l +--- bc/scan.l.orig ++++ bc/scan.l +@@ -59,7 +59,7 @@ int yywrap (void); + /* Have input call the following function. */ + #undef YY_INPUT + #define YY_INPUT(buf,result,max_size) \ +- bcel_input((char *)buf, (yy_size_t *)&result, max_size) ++ result = bcel_input((char *)buf, max_size) + + /* Variables to help interface editline with bc. */ + static const char *bcel_line = (char *)NULL; +@@ -70,10 +70,11 @@ static int bcel_len = 0; + stdin, use editline. Otherwise, just read it. + */ + +-static void +-bcel_input (char *buf, yy_size_t *result, int max) ++static int ++bcel_input (char *buf, int max) + { + ssize_t rdsize; ++ int result; + if (!edit || yyin != stdin) + { + while ( (rdsize = read( fileno(yyin), buf, max )) < 0 ) +@@ -82,8 +83,7 @@ bcel_input (char *buf, yy_size_t *result, int max) + yyerror( "read() in flex scanner failed" ); + bc_exit (1); + } +- *result = (yy_size_t) rdsize; +- return; ++ return rdsize; + } + + /* Do we need a new string? */ +@@ -92,9 +92,8 @@ bcel_input (char *buf, yy_size_t *result, int max) + bcel_line = el_gets(edit, &bcel_len); + if (bcel_line == NULL) { + /* end of file */ +- *result = 0; + bcel_len = 0; +- return; ++ return 0; + } + if (bcel_len != 0) + history (hist, &histev, H_ENTER, bcel_line); +@@ -104,16 +103,17 @@ bcel_input (char *buf, yy_size_t *result, int max) + if (bcel_len <= max) + { + strncpy (buf, bcel_line, bcel_len); +- *result = bcel_len; ++ result = bcel_len; + bcel_len = 0; + } + else + { + strncpy (buf, bcel_line, max); +- *result = max; ++ result = max; + bcel_line += max; + bcel_len -= max; + } ++ return result; + } + #endif +