[CODE][BUG] Exploitable bug in do_flee/do_simple_move

From: Mike Breuer (mbreuer@new.rr.com)
Date: 09/11/01

Hi all:

I discovered this bug last night, and thought I'd send it in.  The only
way I've found to exploit it is if you have a spec_proc in your MUD that
handles normal movement commands (north, east, south, etc).  For
details, read on:

I recently implemented a spec_proc for a "quest_stone" which glows when
you are in a certain type of room.  To cause the glow, the proc handles
normal movement commands and then sets the ITEM_GLOW property based on
the stone's (or char's, if carried) current room.

Shortly after I implemented the object, I noticed a problem with the
flee command.  do_flee calls do_simple_move:

 if (do_simple_move(ch, attempt, TRUE)) {
   send_to_char("You flee head over heels.\r\n", ch);
   if (was_fighting && !IS_NPC(ch)) {
     loss = GET_MAX_HIT(was_fighting) - GET_HIT(was_fighting);
     loss *= GET_LEVEL(was_fighting);
     gain_exp(ch, -loss);
 } else {
   act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);

Unfortunately, do_simple_move was calling my stone's spec proc, which
allowed the movement and returned TRUE indicating that the command was
handled.  do_simple_move does not check whether the player actually
moved...it only returns 0 to show that the do_simple_move function did
not directly move the player.

This means, that even though the player successfully escaped from the
room where he/she was fighting, the experience loss was never applied.
I recommend two possible fixes for this problem:

First, a stopgap fix:

In do_flee:
+ room_rnum orig_room;


+ orig_room = ch->in_room;
+ do_simple_move(ch, attempt, TRUE);

- if (do_simple_move(ch, attempt, TRUE)) {
+ if (orig_room != ch->in_room) {
    send_to_char("You flee head over heels.\r\n", ch);
    if (was_fighting && !IS_NPC(ch)) {

I have not yet had time to play with the other fix, but I think
do_simple_move should be modified to hang on to the original room, and
then all of the return statements replaced with something like:

return (orig_room != ch->in_room);

Before I feel comfortable with this change, I will need to go through
all the calls to do_simple_move to make sure that nothing relies on the
old, and in my view incorrect, behavior.


   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |

This archive was generated by hypermail 2b30 : 12/06/01 PST