fix PR #1254 - avoid signed integer overflow

Pull request from mkuoppal:  avoid integer overflow when user types
digits and they're combined into a number by successively multiplying
intermediate value by 10 and adding new digit.  Needed to avoid
triggering undefined behavior if the value overflows the largest
signed integer (actually long int).

This is a much more general fix than the code in the pull request,
which imposed an arbitrary limit for one aspect of tty input.

I'm not convinced that integer.h was the right place to add the new
AppendLongDigit() macro.  I may not have caught all the places where
it is needed.  files.c accumulates a value from digits but uses
unsigned int, so overflow won't trigger undefined behavior (although
it presumably ends up with a different value than what was intended).
options.c and coloratt.c accumulate smaller integers and have a limit
on the number of digits they'll use, so can't overflow.

Fixes #1254
This commit is contained in:
PatR
2024-06-09 14:17:14 -07:00
parent 50e9b7f404
commit 05cbbc7181
6 changed files with 44 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 integer.h $NHDT-Date: 1596498539 2020/08/03 23:48:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.8 $ */
/* NetHack 3.7 integer.h $NHDT-Date: 1717967331 2024/06/09 21:08:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.12 $ */
/* Copyright (c) 2016 by Michael Allison */
/* NetHack may be freely redistributed. See license for details. */
@@ -101,4 +101,13 @@ typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
/* for non-negative L, calculate L * 10 + D, avoiding signed overflow;
yields -1 if overflow would have happened;
assumes compiler will optimize the constants */
#define AppendLongDigit(L,D) \
(((L) < LONG_MAX / 10L \
|| ((L) == LONG_MAX / 10L && (D) <= LONG_MAX % 10L)) \
? (L) * 10L + (D) \
: -1L)
#endif /* INTEGER_H */