give: Fix integer overflows on silly third arguments
give() silently caps the resulting number of items to 0..ITEM_MAX. However, its test for "< 0" suffers integer overflow on two's complement machines (i.e. practically everywhere) when the amount argument is INT_MIN. give() proceeds as if the result was in range: it sets the number of items to (short)(n + INT_MIN), telexes the owner that INT_MIN items were stolen (obviously bogus), and tells the deity that there are now n + INT_MIN items in X,Y. On common machines, (short)(n + INT_MIN) == n, i.e. nothing is given. On an oddball machine with short as wide as int, the cast to short does nothing, item_prewrite() oopses, and corrects the number of items to zero. In both cases, output and telegram lie. Likewise, its test for "> ITEM_MAX" suffers integer overflow for sufficiently big amount arguments. Again, give() proceeds as if the result was in range: it sets the number of items to (short)(n + amt), telexes the owner that -amt items were stolen (obviously bogus), and tells the deity that there are now close to INT_MIN items in X,Y. On common machines, (short)(n + amt) = n + INT_MAX - amt - 1, i.e. some items are stolen. On an oddball machine with short as wide as int, the cast to short does nothing, item_prewrite() oopses, and corrects the number of items to zero. Again, output and telegram lie. Aside: setsector can suffer similar overflows, but it reports the resulting change correctly. Good enough. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This commit is contained in:
parent
546e1220e0
commit
9aaf609359
3 changed files with 10 additions and 10 deletions
|
@ -29,6 +29,7 @@
|
|||
* Known contributors to this file:
|
||||
* David Muir Sharnoff
|
||||
* Steve McClure, 1997
|
||||
* Markus Armbruster, 2004-2013
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
@ -65,11 +66,11 @@ give(void)
|
|||
if (!check_sect_ok(§))
|
||||
return RET_FAIL;
|
||||
n = sect.sct_item[ip->i_uid];
|
||||
if (amt < 0 && -amt > n) {
|
||||
if (amt < 0 && n + amt < 0)
|
||||
m = 0;
|
||||
} else if (amt > 0 && amt + n > ITEM_MAX) {
|
||||
else if (amt > 0 && n > ITEM_MAX - amt)
|
||||
m = ITEM_MAX;
|
||||
} else
|
||||
else
|
||||
m = n + amt;
|
||||
sect.sct_item[ip->i_uid] = m;
|
||||
putsect(§);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue