Re: [Newbie] - Buf overflow problems

From: Francis Hotchkiss (fhotch@buffnet.net)
Date: 02/13/99


> From: Tom Dailey <tomd@waymark.net>
<SNIP>
> The following is the code from within the function: Any help is
> appreciated...we're stuck on this buf var because
> it seems to be overflowing.
It wasn't a buf overflow it was this:
<snip unneeded code>
>          if(!vict) {
>            if(GET_POS(ch) == POS_FIGHTING) { vict = FIGHTING(ch); }
>          else {
>            for (vict = world[ch->in_room].people; vict; vict =
vict->next_in_room) {
>              if (FIGHTING(vict) == ch && !number(0, 3)) { break; }
>            }
>          }
<snipped rest of code>
Thre problem was that you were only setting the vict cariable to whoever the
char was fighting.  This caused a problem when you tried throwing a potion
while not fighting, ie, the following line tried calling a vict variable that
wasn't initalized all the time:
>                 sprintf(buf, "You throw %s and it shatters on %s!\r\n",
>                  obj->short_description, GET_NAME(vict));

I added a warning against that, and changed a bunch of your
sprintf..send_to_char to act

here is the fixed version
-Astaroth

ACMD(do_throw)
{
  int dam, spell, level;
  struct char_data *vict;
  struct obj_data *obj;

  two_arguments(argument, buf, arg);

  if(!*buf && !*arg) {
    send_to_char("Usage: Throw <item> [target]\r\n", ch);
    return;
  }

  if(!has_skill(ch, SKILL_THROW)) {
    send_to_char("You do not know how to throw things with any accuracy.\r\n",
ch);
    return;
  }

  generic_find(buf, FIND_OBJ_INV, ch, 0, &obj);

  if(!obj) {
    send_to_char("You do not appear to have that.\r\n", ch);
    return;
  }

  if(*arg) {
    if(!(vict = get_char_room_vis(ch, arg))) {
      send_to_char("They dont seem to be here.\r\n", ch);
      return;
    }
  }

  switch(GET_OBJ_TYPE(obj)) {
  case ITEM_THROWN:
    if(!vict) {
      send_to_char("Throw it at whom?\r\n", ch);
      return;
    }
    if(skill_check(ch, SKILL_THROW, 0, FALSE)) {
      dam = dice(GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2));
      sprintf(buf, "Damage: %d\r\n", dam);
      send_to_char(buf, ch);
      damage(ch, vict, dam, TYPE_HIT);
    } else {
      act("You throw $p at $N, but miss.", FALSE, ch, obj, vict, TO_CHAR);
      act("$n throw $p at $N, but misses.", TRUE, ch, obj, vict, TO_ROOM);
    }

    if(GET_OBJ_VAL(obj, 0) <= 1)
      extract_obj(obj);
    else
      GET_OBJ_VAL(obj, 0) -= 1;
    break;

  case ITEM_POTION:
    spell = GET_OBJ_VAL(obj, 1);
    level = GET_OBJ_VAL(obj, 0);

    if(spell == PRAYER_EARTHQUAKE || spell == SPELL_BLACK_RAIN) {
      if(!(skill_check(ch, SKILL_THROW, 5, 0))) {
        act("You throw $p and it shatters with just a puff of smoke.", FALSE,
ch, obj, 0, TO_CHAR);
        act("$n throws $p and it shatters with just a puff of smoke.", FALSE,
ch, obj, 0, TO_ROOM);
      } else {
        act("You throw $p and it shatters on the ground!", FALSE, ch, obj, 0,
TO_CHAR);
        act("$n throws $p and it shatters on the ground!", TRUE, ch, obj, 0,
TO_ROOM);
        mag_areas(level, ch, spell, SAVING_SPELL);
      }
    } else {
      if(!vict) {
        if(GET_POS(ch) == POS_FIGHTING)
          vict = FIGHTING(ch);
        else {
          for (vict = world[ch->in_room].people; vict; vict =
vict->next_in_room) {
            if (FIGHTING(vict) == ch && !number(0, 3))
              break;
          }
          if (!vict) { /* If there is still no victim... */
            send_to_char("You aren't fighting anyone!\r\n", ch);
            return;
          }
        }
      }
      if(!(skill_check(ch, SKILL_THROW, 0, 0))) {
        act("You fumble $p while trying to throw it!", FALSE, ch, obj, 0,
TO_CHAR);
        act("$n fumbles $p while trying to throw it!", FALSE, ch, obj, 0,
TO_ROOM);
      } else {
        act("You throw $p and it shatters on $N!", FALSE, ch, obj, vict,
TO_CHAR);
        act("$n throws $p and it shatters on $N!", TRUE, ch, obj, vict,
TO_ROOM);
        mag_damage(level, ch, vict, spell, SAVING_SPELL);
      }
    }
    extract_obj(obj);
    break;
  default:
    /* I moved this down here so you wouldn't fail the check before.
       Now you can have throwable items besides potions... */
    send_to_char("You can't throw that.\r\n", ch);
    break;
  }

  WAIT_STATE(ch, PULSE_VIOLENCE*2); /* I moved this down here because it was
                                        common to your two cases */

  if (FIGHTING(vict) != ch) /* Start them fighting, if they aren't already */
    FIGHTING(vict) == ch;
}


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/15/00 PST