Subject: bug#42660: closed (emacs-27.1-rc1 and UBsan findings)

From: [email-masked] (GNU bug Tracking System)
Date: Tue, 18 Aug 2020 01:00:03 +0000

Your bug report

#42660: emacs-27.1-rc1 and UBsan findings

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
42660: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=42660
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: emacs-27.1-rc1 and UBsan findings
From: Paul Eggert <[email-masked]>
To: [email-masked]
Cc: Lars Ingebrigtsen <[email-masked]>, [email-masked]
Date: Mon, 17 Aug 2020 17:58:59 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

The bug is unlikely to lead to a real problem, so I installed the attached 
low-priority patch into the master branch rather than into emacs-27. Closing the 
bug report as fixed.
>From 9905001e4b0c9dc0a90cefdd9530a90d07a17b99 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Mon, 17 Aug 2020 17:54:44 -0700
Subject: [PATCH] Fix glitch uncovered by gcc -fsanitize=undefined

* src/ccl.c (ccl_driver): Defend against signed integer
overflow (Bug#42660).  Perhaps some of this is unnecessary,
but it is safe and ccl.c is low-priority these days.
---
 src/ccl.c | 104 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 85 insertions(+), 19 deletions(-)

diff --git a/src/ccl.c b/src/ccl.c
index e85cfa6cdf..86debeef0e 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1142,19 +1142,52 @@ #define EXCMD (field1 >> 6)
 	ccl_expr_self:
 	  switch (op)
 	    {
-	    case CCL_PLUS: reg[rrr] += i; break;
-	    case CCL_MINUS: reg[rrr] -= i; break;
-	    case CCL_MUL: reg[rrr] *= i; break;
-	    case CCL_DIV: reg[rrr] /= i; break;
+	    case CCL_PLUS: INT_ADD_WRAPV (reg[rrr], i, &reg[rrr]); break;
+	    case CCL_MINUS: INT_SUBTRACT_WRAPV (reg[rrr], i, &reg[rrr]); break;
+	    case CCL_MUL: INT_MULTIPLY_WRAPV (reg[rrr], i, &reg[rrr]); break;
+	    case CCL_DIV:
+	      if (!i)
+		CCL_INVALID_CMD;
+	      if (!INT_DIVIDE_OVERFLOW (reg[rrr], i))
+		reg[rrr] /= i;
+	      break;
 	    case CCL_MOD: reg[rrr] %= i; break;
+	      if (!i)
+		CCL_INVALID_CMD;
+	      reg[rrr] = i == -1 ? 0 : reg[rrr] % i;
+	      break;
 	    case CCL_AND: reg[rrr] &= i; break;
 	    case CCL_OR: reg[rrr] |= i; break;
 	    case CCL_XOR: reg[rrr] ^= i; break;
-	    case CCL_LSH: reg[rrr] <<= i; break;
-	    case CCL_RSH: reg[rrr] >>= i; break;
-	    case CCL_LSH8: reg[rrr] <<= 8; reg[rrr] |= i; break;
+	    case CCL_LSH:
+	      if (i < 0)
+		CCL_INVALID_CMD;
+	      reg[rrr] = i < UINT_WIDTH ? (unsigned) reg[rrr] << i : 0;
+	      break;
+	    case CCL_RSH:
+	      if (i < 0)
+		CCL_INVALID_CMD;
+	      reg[rrr] = reg[rrr] >> min (i, INT_WIDTH - 1);
+	      break;
+	    case CCL_LSH8:
+	      reg[rrr] = (unsigned) reg[rrr] << 8;
+	      reg[rrr] |= i;
+	      break;
 	    case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break;
-	    case CCL_DIVMOD: reg[7] = reg[rrr] % i; reg[rrr] /= i; break;
+	    case CCL_DIVMOD:
+	      if (!i)
+		CCL_INVALID_CMD;
+	      if (i == -1)
+		{
+		  reg[7] = 0;
+		  INT_SUBTRACT_WRAPV (0, reg[rrr], &reg[rrr]);
+		}
+	      else
+		{
+		  reg[7] = reg[rrr] % i;
+		  reg[rrr] /= i;
+		}
+	      break;
 	    case CCL_LS: reg[rrr] = reg[rrr] < i; break;
 	    case CCL_GT: reg[rrr] = reg[rrr] > i; break;
 	    case CCL_EQ: reg[rrr] = reg[rrr] == i; break;
@@ -1204,19 +1237,52 @@ #define EXCMD (field1 >> 6)
 	ccl_set_expr:
 	  switch (op)
 	    {
-	    case CCL_PLUS: reg[rrr] = i + j; break;
-	    case CCL_MINUS: reg[rrr] = i - j; break;
-	    case CCL_MUL: reg[rrr] = i * j; break;
-	    case CCL_DIV: reg[rrr] = i / j; break;
-	    case CCL_MOD: reg[rrr] = i % j; break;
+	    case CCL_PLUS: INT_ADD_WRAPV (i, j, &reg[rrr]); break;
+	    case CCL_MINUS: INT_SUBTRACT_WRAPV (i, j, &reg[rrr]); break;
+	    case CCL_MUL: INT_MULTIPLY_WRAPV (i, j, &reg[rrr]); break;
+	    case CCL_DIV:
+	      if (!j)
+		CCL_INVALID_CMD;
+	      if (!INT_DIVIDE_OVERFLOW (i, j))
+		i /= j;
+	      reg[rrr] = i;
+	      break;
+	    case CCL_MOD:
+	      if (!j)
+		CCL_INVALID_CMD;
+	      reg[rrr] = j == -1 ? 0 : i % j;
+	      break;
 	    case CCL_AND: reg[rrr] = i & j; break;
 	    case CCL_OR: reg[rrr] = i | j; break;
 	    case CCL_XOR: reg[rrr] = i ^ j; break;
-	    case CCL_LSH: reg[rrr] = i << j; break;
-	    case CCL_RSH: reg[rrr] = i >> j; break;
-	    case CCL_LSH8: reg[rrr] = (i << 8) | j; break;
+	    case CCL_LSH:
+	      if (j < 0)
+		CCL_INVALID_CMD;
+	      reg[rrr] = j < UINT_WIDTH ? (unsigned) i << j : 0;
+	      break;
+	    case CCL_RSH:
+	      if (j < 0)
+		CCL_INVALID_CMD;
+	      reg[rrr] = i >> min (j, INT_WIDTH - 1);
+	      break;
+	    case CCL_LSH8:
+	      reg[rrr] = ((unsigned) i << 8) | j;
+	      break;
 	    case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break;
-	    case CCL_DIVMOD: reg[rrr] = i / j; reg[7] = i % j; break;
+	    case CCL_DIVMOD:
+	      if (!j)
+		CCL_INVALID_CMD;
+	      if (j == -1)
+		{
+		  INT_SUBTRACT_WRAPV (0, reg[rrr], &reg[rrr]);
+		  reg[7] = 0;
+		}
+	      else
+		{
+		  reg[rrr] = i / j;
+		  reg[7] = i % j;
+		}
+	      break;
 	    case CCL_LS: reg[rrr] = i < j; break;
 	    case CCL_GT: reg[rrr] = i > j; break;
 	    case CCL_EQ: reg[rrr] = i == j; break;
@@ -1225,7 +1291,7 @@ #define EXCMD (field1 >> 6)
 	    case CCL_NE: reg[rrr] = i != j; break;
 	    case CCL_DECODE_SJIS:
 	      {
-		i = (i << 8) | j;
+		i = ((unsigned) i << 8) | j;
 		SJIS_TO_JIS (i);
 		reg[rrr] = i >> 8;
 		reg[7] = i & 0xFF;
@@ -1233,7 +1299,7 @@ #define EXCMD (field1 >> 6)
 	      }
 	    case CCL_ENCODE_SJIS:
 	      {
-		i = (i << 8) | j;
+		i = ((unsigned) i << 8) | j;
 		JIS_TO_SJIS (i);
 		reg[rrr] = i >> 8;
 		reg[7] = i & 0xFF;
-- 
2.17.1

Subject: emacs-27.1-rc1 and UBsan findings
From: Jeffrey Walton <[email-masked]>
To: [email-masked]
Date: Sat, 1 Aug 2020 16:34:22 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

I believe these additional failures are due to -fsanitize=undefined
-fno-sanitize-recover=all.

SUMMARY OF TEST RESULTS
-----------------------
Files examined: 267
Ran 3850 tests, 7 failed to run, 3763 results as expected, 1
unexpected, 86 skipped
1 files did not contain any tests:
  src/emacs-module-tests.log
1 files did not finish:
  lisp/international/ccl-tests.log
1 files contained unexpected results:
  lisp/cedet/srecode-utest-template.log
Makefile:319: recipe for target 'check-doit' failed
make[2]: *** [check-doit] Error 2
make[2]: Leaving directory '/home/jwalton/Build-Scripts/emacs-27.1/test'
Makefile:289: recipe for target 'check' failed
make[1]: *** [check] Error 2
make[1]: Leaving directory '/home/jwalton/Build-Scripts/emacs-27.1/test'
Makefile:959: recipe for target 'check' failed
make: *** [check] Error 2

Here's a typical failure:

$ cat emacs-27.1/test/lisp/international/ccl-tests.log
Running 7 tests (2020-08-01 16:28:12-0400, selector `(not (or (tag
:expensive-test) (tag :unstable)))')
   passed  1/7  ccl-compile-midi (0.000181 sec)
   passed  2/7  ccl-compile-pgg (0.000093 sec)
   passed  3/7  ccl-dump-midi (0.005956 sec)
   passed  4/7  ccl-dump-pgg (0.000111 sec)
Package pgg-def is deprecated
Package pgg-parse is deprecated
Package pgg is deprecated
ccl.c:1146:29: runtime error: left shift of 1246883553 by 1 places
cannot be represented in type 'int'