Merge pull request #84 from tbamud/crash-bug-in-object-drop-script

Crash bug in object drop script
This commit is contained in:
Thomas Arp 2020-03-08 23:57:15 +01:00 committed by GitHub
commit 1f520546b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 26 deletions

View file

@ -52,11 +52,12 @@ static void wear_message(struct char_data *ch, struct obj_data *obj, int where);
static void perform_put(struct char_data *ch, struct obj_data *obj, struct obj_data *cont) static void perform_put(struct char_data *ch, struct obj_data *obj, struct obj_data *cont)
{ {
long object_id = obj_script_id(obj);
if (!drop_otrigger(obj, ch)) if (!drop_otrigger(obj, ch))
return; return;
if (!obj) /* object might be extracted by drop_otrigger */ if (!has_obj_by_uid_in_lookup_table(object_id)) /* object might be extracted by drop_otrigger */
return; return;
if ((GET_OBJ_VAL(cont, 0) > 0) && if ((GET_OBJ_VAL(cont, 0) > 0) &&
@ -409,24 +410,27 @@ static void perform_drop_gold(struct char_data *ch, int amount, byte mode, room_
WAIT_STATE(ch, PULSE_VIOLENCE); /* to prevent coin-bombing */ WAIT_STATE(ch, PULSE_VIOLENCE); /* to prevent coin-bombing */
obj = create_money(amount); obj = create_money(amount);
if (mode == SCMD_DONATE) { if (mode == SCMD_DONATE) {
send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n"); send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n");
act("$n throws some gold into the air where it disappears in a puff of smoke!", act("$n throws some gold into the air where it disappears in a puff of smoke!",
FALSE, ch, 0, 0, TO_ROOM); FALSE, ch, 0, 0, TO_ROOM);
obj_to_room(obj, RDR); obj_to_room(obj, RDR);
act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM); act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM);
} else { } else {
char buf[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH];
long object_id = obj_script_id(obj);
if (!drop_wtrigger(obj, ch)) { if (!drop_wtrigger(obj, ch)) {
extract_obj(obj); if (has_obj_by_uid_in_lookup_table(object_id))
extract_obj(obj);
return; return;
} }
snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount)); snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount));
act(buf, TRUE, ch, 0, 0, TO_ROOM); act(buf, TRUE, ch, 0, 0, TO_ROOM);
send_to_char(ch, "You drop some gold.\r\n"); send_to_char(ch, "You drop some gold.\r\n");
obj_to_room(obj, IN_ROOM(ch)); obj_to_room(obj, IN_ROOM(ch));
} }
} else { } else {
char buf[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH];
@ -447,13 +451,20 @@ static int perform_drop(struct char_data *ch, struct obj_data *obj,
{ {
char buf[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH];
int value; int value;
long object_id = obj_script_id(obj);
if (!drop_otrigger(obj, ch)) if (!drop_otrigger(obj, ch))
return 0; return 0;
if (!has_obj_by_uid_in_lookup_table(object_id))
return 0; // item was extracted by script
if ((mode == SCMD_DROP) && !drop_wtrigger(obj, ch)) if ((mode == SCMD_DROP) && !drop_wtrigger(obj, ch))
return 0; return 0;
if (!has_obj_by_uid_in_lookup_table(object_id))
return 0; // item was extracted by script
if (OBJ_FLAGGED(obj, ITEM_NODROP) && !PRF_FLAGGED(ch, PRF_NOHASSLE)) { if (OBJ_FLAGGED(obj, ITEM_NODROP) && !PRF_FLAGGED(ch, PRF_NOHASSLE)) {
snprintf(buf, sizeof(buf), "You can't %s $p, it must be CURSED!", sname); snprintf(buf, sizeof(buf), "You can't %s $p, it must be CURSED!", sname);
act(buf, FALSE, ch, obj, 0, TO_CHAR); act(buf, FALSE, ch, obj, 0, TO_CHAR);

View file

@ -2994,12 +2994,23 @@ void init_lookup_table(void)
} }
} }
static struct char_data *find_char_by_uid_in_lookup_table(long uid) static inline struct lookup_table_t *get_bucket_head(long uid)
{ {
int bucket = (int) (uid & (BUCKET_COUNT - 1)); int bucket = (int) (uid & (BUCKET_COUNT - 1));
struct lookup_table_t *lt = &lookup_table[bucket]; return &lookup_table[bucket];
}
static inline struct lookup_table_t *find_element_by_uid_in_lookup_table(long uid)
{
struct lookup_table_t *lt = get_bucket_head(uid);
for (;lt && lt->uid != uid ; lt = lt->next) ; for (;lt && lt->uid != uid ; lt = lt->next) ;
return lt;
}
static struct char_data *find_char_by_uid_in_lookup_table(long uid)
{
struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid);
if (lt) if (lt)
return (struct char_data *)(lt->c); return (struct char_data *)(lt->c);
@ -3010,10 +3021,7 @@ static struct char_data *find_char_by_uid_in_lookup_table(long uid)
static struct obj_data *find_obj_by_uid_in_lookup_table(long uid) static struct obj_data *find_obj_by_uid_in_lookup_table(long uid)
{ {
int bucket = (int) (uid & (BUCKET_COUNT - 1)); struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid);
struct lookup_table_t *lt = &lookup_table[bucket];
for (;lt && lt->uid != uid ; lt = lt->next) ;
if (lt) if (lt)
return (struct obj_data *)(lt->c); return (struct obj_data *)(lt->c);
@ -3022,10 +3030,16 @@ static struct obj_data *find_obj_by_uid_in_lookup_table(long uid)
return NULL; return NULL;
} }
int has_obj_by_uid_in_lookup_table(long uid)
{
struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid);
return lt != NULL;
}
void add_to_lookup_table(long uid, void *c) void add_to_lookup_table(long uid, void *c)
{ {
int bucket = (int) (uid & (BUCKET_COUNT - 1)); struct lookup_table_t *lt = get_bucket_head(uid);
struct lookup_table_t *lt = &lookup_table[bucket];
if (lt && lt->uid == uid) { if (lt && lt->uid == uid) {
log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->c, c); log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->c, c);
@ -3036,6 +3050,7 @@ void add_to_lookup_table(long uid, void *c)
for (;lt && lt->next; lt = lt->next) for (;lt && lt->next; lt = lt->next)
if (lt->next->uid == uid) { if (lt->next->uid == uid) {
log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->next->c, c); log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->next->c, c);
lt->next->c = c;
return; return;
} }
@ -3054,9 +3069,7 @@ void remove_from_lookup_table(long uid)
if (uid == 0) if (uid == 0)
return; return;
for (;lt;lt = lt->next) flt = find_element_by_uid_in_lookup_table(uid);
if (lt->uid == uid)
flt = lt;
if (flt) { if (flt) {
for (lt = &lookup_table[bucket];lt->next != flt;lt = lt->next) for (lt = &lookup_table[bucket];lt->next != flt;lt = lt->next)

View file

@ -449,6 +449,8 @@ void wld_command_interpreter(room_data *room, char *argument);
// id helpers // id helpers
extern long char_script_id(char_data *ch); extern long char_script_id(char_data *ch);
extern long obj_script_id(obj_data *obj); extern long obj_script_id(obj_data *obj);
extern int has_obj_by_uid_in_lookup_table(long uid);
#define room_script_id(room) ((long)(room)->number + ROOM_ID_BASE) #define room_script_id(room) ((long)(room)->number + ROOM_ID_BASE)
#endif /* _DG_SCRIPTS_H_ */ #endif /* _DG_SCRIPTS_H_ */

View file

@ -462,6 +462,7 @@ int receive_mtrigger(char_data *ch, char_data *actor, obj_data *obj)
trig_data *t; trig_data *t;
char buf[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH];
int ret_val; int ret_val;
long object_id = obj_script_id(obj);
if (!SCRIPT_CHECK(ch, MTRIG_RECEIVE) || AFF_FLAGGED(ch, AFF_CHARM)) if (!SCRIPT_CHECK(ch, MTRIG_RECEIVE) || AFF_FLAGGED(ch, AFF_CHARM))
return 1; return 1;
@ -471,9 +472,10 @@ int receive_mtrigger(char_data *ch, char_data *actor, obj_data *obj)
(rand_number(1, 100) <= GET_TRIG_NARG(t))){ (rand_number(1, 100) <= GET_TRIG_NARG(t))){
ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0); ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0);
ADD_UID_VAR(buf, t, obj_script_id(obj), "object", 0); ADD_UID_VAR(buf, t, object_id, "object", 0);
ret_val = script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); ret_val = script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW);
if (DEAD(actor) || DEAD(ch) || obj->carried_by != actor) // check for purged item before dereferencing.
if (DEAD(actor) || DEAD(ch) || !has_obj_by_uid_in_lookup_table(object_id) || obj->carried_by != actor)
return 0; return 0;
else else
return ret_val; return ret_val;
@ -1118,6 +1120,7 @@ int drop_wtrigger(obj_data *obj, char_data *actor)
trig_data *t; trig_data *t;
char buf[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH];
int ret_val; int ret_val;
long object_id = obj_script_id(obj);
if (!actor || !SCRIPT_CHECK(&world[IN_ROOM(actor)], WTRIG_DROP)) if (!actor || !SCRIPT_CHECK(&world[IN_ROOM(actor)], WTRIG_DROP))
return 1; return 1;
@ -1127,9 +1130,10 @@ int drop_wtrigger(obj_data *obj, char_data *actor)
if (TRIGGER_CHECK(t, WTRIG_DROP) && if (TRIGGER_CHECK(t, WTRIG_DROP) &&
(rand_number(1, 100) <= GET_TRIG_NARG(t))) { (rand_number(1, 100) <= GET_TRIG_NARG(t))) {
ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0); ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0);
ADD_UID_VAR(buf, t, obj_script_id(obj), "object", 0); ADD_UID_VAR(buf, t, object_id, "object", 0);
ret_val = script_driver(&room, t, WLD_TRIGGER, TRIG_NEW); ret_val = script_driver(&room, t, WLD_TRIGGER, TRIG_NEW);
if (obj->carried_by != actor) // check for purged object before dereferencing.
if (!has_obj_by_uid_in_lookup_table(object_id) || obj->carried_by != actor)
return 0; return 0;
else else
return ret_val; return ret_val;