From 51241f66ad6e78cf56b91c41e524c00a1d5abeb2 Mon Sep 17 00:00:00 2001 From: Haru Date: Sat, 21 Sep 2013 03:47:19 +0200 Subject: Fixed a potentially negative array subscript causing a mapserver crash - Fixes bugreport:7717, special thanks to quesoph http://hercules.ws/board/tracker/issue-7717-map-crash-when-warping-on-a-floating-npc/ - Also changed various map[foo].index to the map_id2index(foo) macro. Signed-off-by: Haru --- src/map/atcommand.c | 110 ++++++++++++++++++++++------------------------------ src/map/chrif.c | 2 +- src/map/instance.c | 2 +- src/map/intif.c | 5 +-- src/map/map.c | 2 +- src/map/mob.c | 26 ++++++------- src/map/npc.c | 62 ++++++++++++----------------- src/map/pc.c | 15 ++++--- 8 files changed, 95 insertions(+), 129 deletions(-) (limited to 'src') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 2466c2cca..8eb3bfd44 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4223,8 +4223,7 @@ ACMD(nuke) /*========================================== * @tonpc *------------------------------------------*/ -ACMD(tonpc) -{ +ACMD(tonpc) { char npcname[NAME_LENGTH+1]; struct npc_data *nd; @@ -4238,7 +4237,7 @@ ACMD(tonpc) } if ((nd = npc->name2id(npcname)) != NULL) { - if (pc->setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0) + if (nd->bl.m != -1 && pc->setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0) clif->message(fd, msg_txt(0)); // Warped. else return false; @@ -7637,7 +7636,7 @@ return true;\ clif->message(sd->fd," "); clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) clif->message(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. - return 1; + return true; } for (i = 0; flag_name[i]; i++) flag_name[i] = TOLOWER(flag_name[i]); //lowercase @@ -8146,28 +8145,20 @@ ACMD(itemlist) nullpo_retr(-1, sd); - if( strcmp(command+1, "storagelist") == 0 ) - { + if( strcmp(command+1, "storagelist") == 0 ) { location = "storage"; items = sd->status.storage.items; size = MAX_STORAGE; - } - else - if( strcmp(command+1, "cartlist") == 0 ) - { - location = "cart"; - items = sd->status.cart; - size = MAX_CART; - } - else - if( strcmp(command+1, "itemlist") == 0 ) - { - location = "inventory"; - items = sd->status.inventory; - size = MAX_INVENTORY; - } - else - return 1; + } else if( strcmp(command+1, "cartlist") == 0 ) { + location = "cart"; + items = sd->status.cart; + size = MAX_CART; + } else if( strcmp(command+1, "itemlist") == 0 ) { + location = "inventory"; + items = sd->status.inventory; + size = MAX_INVENTORY; + } else + return false; StrBuf->Init(&buf); @@ -8196,8 +8187,7 @@ ACMD(itemlist) else StrBuf->Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid); - if( it->equip ) - { + if( it->equip ) { char equipstr[CHAT_SIZE_MAX]; strcpy(equipstr, msg_txt(1333)); // | equipped: if( it->equip & EQP_GARMENT ) @@ -8236,52 +8226,46 @@ ACMD(itemlist) clif->message(fd, StrBuf->Value(&buf)); StrBuf->Clear(&buf); - if( it->card[0] == CARD0_PET ) - {// pet egg + if( it->card[0] == CARD0_PET ) { + // pet egg if (it->card[3]) StrBuf->Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named) else StrBuf->Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed) - } - else - if(it->card[0] == CARD0_FORGE) - {// forged item - StrBuf->Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) + } else if(it->card[0] == CARD0_FORGE) { + // forged item + StrBuf->Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) + } else if(it->card[0] == CARD0_CREATE) { + // created item + StrBuf->Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) + } else { + // normal item + int counter2 = 0; + + for( j = 0; j < itd->slot; ++j ) { + struct item_data* card; + + if( it->card[j] == 0 || (card = itemdb->exists(it->card[j])) == NULL ) + continue; + + counter2++; + + if( counter2 == 1 ) + StrBuf->AppendStr(&buf, msg_txt(1352)); // -> (card(s): + + if( counter2 != 1 ) + StrBuf->AppendStr(&buf, ", "); + + StrBuf->Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); } - else - if(it->card[0] == CARD0_CREATE) - {// created item - StrBuf->Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) - } - else - {// normal item - int counter2 = 0; - - for( j = 0; j < itd->slot; ++j ) - { - struct item_data* card; - - if( it->card[j] == 0 || (card = itemdb->exists(it->card[j])) == NULL ) - continue; - - counter2++; - - if( counter2 == 1 ) - StrBuf->AppendStr(&buf, msg_txt(1352)); // -> (card(s): - - if( counter2 != 1 ) - StrBuf->AppendStr(&buf, ", "); - - StrBuf->Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); - } - - if( counter2 > 0 ) - StrBuf->AppendStr(&buf, ")"); - } + + if( counter2 > 0 ) + StrBuf->AppendStr(&buf, ")"); + } if( StrBuf->Length(&buf) > 0 ) clif->message(fd, StrBuf->Value(&buf)); - + StrBuf->Clear(&buf); } diff --git a/src/map/chrif.c b/src/map/chrif.c index c79cf9e4a..53ef808a0 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -348,7 +348,7 @@ int chrif_sendmap(int fd) { WFIFOHEAD(fd, 4 + instance->start_id * 4); WFIFOW(fd,0) = 0x2afa; for(i = 0; i < instance->start_id; i++) - WFIFOW(fd,4+i*4) = map[i].index; + WFIFOW(fd,4+i*4) = map_id2index(i); WFIFOW(fd,2) = 4 + i * 4; WFIFOSET(fd,WFIFOW(fd,2)); diff --git a/src/map/instance.c b/src/map/instance.c index 98a0dfc8f..cb5464b24 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -377,7 +377,7 @@ void instance_del_map(int16 m) { if( map[m].mob_delete_timer != INVALID_TIMER ) iTimer->delete_timer(map[m].mob_delete_timer, iMap->removemobs_timer); - mapindex_removemap( map[m].index ); + mapindex_removemap(map_id2index(m)); // Free memory aFree(map[m].cell); diff --git a/src/map/intif.c b/src/map/intif.c index ac1471d23..634735bd6 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -458,8 +458,7 @@ int intif_party_leave(int party_id,int account_id, int char_id) } // Request keeping party for new map ?? -int intif_party_changemap(struct map_session_data *sd,int online) -{ +int intif_party_changemap(struct map_session_data *sd,int online) { int16 m, mapindex; if (intif->CheckForCharServer()) @@ -468,7 +467,7 @@ int intif_party_changemap(struct map_session_data *sd,int online) return 0; if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 ) - mapindex = map[map[m].instance_src_map].index; + mapindex = map_id2index(map[m].instance_src_map); else mapindex = sd->mapindex; diff --git a/src/map/map.c b/src/map/map.c index d4568766a..865682afc 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3167,7 +3167,7 @@ int map_readallmaps (void) { map[i].index = mapindex_name2id(map[i].name); - if ( index2mapid[map[i].index] != -1 ) { + if ( index2mapid[map_id2index(i)] != -1 ) { ShowWarning("Map %s already loaded!"CL_CLL"\n", map[i].name); if (map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf) { aFree(map[i].cell); diff --git a/src/map/mob.c b/src/map/mob.c index 146f82239..0c1ad0d5d 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -457,8 +457,7 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int /*========================================== * Spawn a single mob on the specified coordinates. *------------------------------------------*/ -int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) -{ +int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) { struct mob_data* md = NULL; int count, lv; @@ -467,26 +466,22 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const lv = (sd) ? sd->status.base_level : 255; - for (count = 0; count < amount; count++) - { + for (count = 0; count < amount; count++) { int c = (class_ >= 0) ? class_ : mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv); md = mob->once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai); if (!md) continue; - if (class_ == MOBID_EMPERIUM) - { - struct guild_castle* gc = guild->mapindex2gc(map[m].index); + if (class_ == MOBID_EMPERIUM) { + struct guild_castle* gc = guild->mapindex2gc(map_id2index(m)); struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL; - if (gc) - { + if (gc) { md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); md->guardian_data->castle = gc; md->guardian_data->number = MAX_GUARDIANS; md->guardian_data->guild_id = gc->guild_id; - if (g) - { + if (g) { md->guardian_data->emblem_id = g->emblem_id; memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); } @@ -497,10 +492,11 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const mob->spawn(md); - if (class_ < 0 && battle_config.dead_branch_active) + if (class_ < 0 && battle_config.dead_branch_active) { //Behold Aegis's masterful decisions yet again... //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3 sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000); + } } return (md) ? md->bl.id : 0; // id of last spawned mob @@ -1182,12 +1178,12 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) { if(nd->subtype != WARP) return 0; //Not a warp - if(nd->u.warp.mapindex != map[target->m].index) + if(nd->u.warp.mapindex != map_id2index(target->m)) return 0; //Does not lead to the same map. cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y); - if (cur_distance < *min_distance) - { //Pick warp that leads closest to target. + if (cur_distance < *min_distance) { + //Pick warp that leads closest to target. *target_nd = nd; *min_distance = cur_distance; return 1; diff --git a/src/map/npc.c b/src/map/npc.c index 51d01d711..20caf2b67 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1952,8 +1952,7 @@ void npc_delsrcfile(const char* name) /// Parses and sets the name and exname of a npc. /// Assumes that m, x and y are already set in nd. -void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) -{ +void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) { const char* p; struct npc_data* dnd;// duplicate npc char newname[NAME_LENGTH]; @@ -1997,8 +1996,8 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y); } while( npc->name2id(newname) != NULL ); - strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index))); - strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index))); + strcpy(this_mapname, (nd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(nd->bl.m)))); + strcpy(other_mapname, (dnd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(dnd->bl.m)))); ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname); ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y); @@ -2627,7 +2626,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch int npc_duplicate4instance(struct npc_data *snd, int16 m) { char newname[NAME_LENGTH]; - if( map[m].instance_id == -1 ) + if( m == -1 || map[m].instance_id == -1 ) return 1; snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id); @@ -2924,8 +2923,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn) } } -const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { int num, class_, m,x,y,xs,ys, i,j; int mob_lv = -1, ai = -1, size = -1; char mapname[32], mobname[NAME_LENGTH]; @@ -2940,14 +2938,13 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st // w3={,} // w4=,,,,{,,} if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 - || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1 - || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2 ) - { + || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1 + || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2 + ) { ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return strchr(start,'\n');// skip and continue } - if( mapindex_name2id(mapname) == 0 ) - { + if( mapindex_name2id(mapname) == 0 ) { ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } @@ -2956,39 +2953,33 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st return strchr(start,'\n');// skip and continue mobspawn.m = (unsigned short)m; - if( x < 0 || x >= map[mobspawn.m].xs || y < 0 || y >= map[mobspawn.m].ys ) - { + if( x < 0 || x >= map[mobspawn.m].xs || y < 0 || y >= map[mobspawn.m].ys ) { ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map[mobspawn.m].name, x, y, (map[mobspawn.m].xs-1), (map[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } // check monster ID if exists! - if( mob->db_checkid(class_) == 0 ) - { + if( mob->db_checkid(class_) == 0 ) { ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } - if( num < 1 || num > 1000 ) - { + if( num < 1 || num > 1000 ) { ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } - if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) - { + if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) { ShowError("npc_parse_mob: Invalid size number %d for mob ID %d (file '%s', line '%d').\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer)); return strchr(start, '\n'); } - if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && ai != -1 ) - { + if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && ai != -1 ) { ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer)); return strchr(start, '\n'); } - if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) - { + if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) { ShowError("npc_parse_mob: Invalid level %d for mob ID %d (file '%s', line '%d').\n", mob_lv, class_, filepath, strline(buffer, start - buffer)); return strchr(start, '\n'); } @@ -3012,8 +3003,8 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st mobspawn.num = 1; } - if (battle_config.force_random_spawn || (mobspawn.x == 0 && mobspawn.y == 0)) - { //Force a random spawn anywhere on the map. + if (battle_config.force_random_spawn || (mobspawn.x == 0 && mobspawn.y == 0)) { + //Force a random spawn anywhere on the map. mobspawn.x = mobspawn.y = 0; mobspawn.xs = mobspawn.ys = -1; } @@ -3032,23 +3023,20 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st safestrncpy(mobspawn.name, mobname, sizeof(mobspawn.name)); //Verify dataset. - if( !mob->parse_dataset(&mobspawn) ) - { + if( !mob->parse_dataset(&mobspawn) ) { ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } //Update mob spawn lookup database db = mob->db(class_); - for( i = 0; i < ARRAYLENGTH(db->spawn); ++i ) - { - if (map[mobspawn.m].index == db->spawn[i].mapindex) - { //Update total + for( i = 0; i < ARRAYLENGTH(db->spawn); ++i ) { + if (map_id2index(mobspawn.m) == db->spawn[i].mapindex) { + //Update total db->spawn[i].qty += mobspawn.num; //Re-sort list for( j = i; j > 0 && db->spawn[j-1].qty < db->spawn[i].qty; --j ); - if( j != i ) - { + if( j != i ) { xs = db->spawn[i].mapindex; ys = db->spawn[i].qty; memmove(&db->spawn[j+1], &db->spawn[j], (i-j)*sizeof(db->spawn[0])); @@ -3057,10 +3045,10 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st } break; } - if (mobspawn.num > db->spawn[i].qty) - { //Insert into list + if (mobspawn.num > db->spawn[i].qty) { + //Insert into list memmove(&db->spawn[i+1], &db->spawn[i], sizeof(db->spawn) -(i+1)*sizeof(db->spawn[0])); - db->spawn[i].mapindex = map[mobspawn.m].index; + db->spawn[i].mapindex = map_id2index(mobspawn.m); db->spawn[i].qty = mobspawn.num; break; } diff --git a/src/map/pc.c b/src/map/pc.c index 995687170..4738d816a 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4825,7 +4825,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if( i != sd->instances ) { m = instances[sd->instance[i]].map[j]; - mapindex = map[m].index; + mapindex = map_id2index(m); stop = true; } } @@ -4839,7 +4839,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if( i != p->instances ) { m = instances[p->instance[i]].map[j]; - mapindex = map[m].index; + mapindex = map_id2index(m); stop = true; } } @@ -4853,7 +4853,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if( i != sd->guild->instances ) { m = instances[sd->guild->instance[i]].map[j]; - mapindex = map[m].index; + mapindex = map_id2index(m); stop = true; } } @@ -5009,8 +5009,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y * 0 = fail or FIXME success (from pc->setpos) * x(1|2) = fail *------------------------------------------*/ -int pc_randomwarp(struct map_session_data *sd, clr_type type) -{ +int pc_randomwarp(struct map_session_data *sd, clr_type type) { int x,y,i=0; int16 m; @@ -5021,13 +5020,13 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type) if (map[sd->bl.m].flag.noteleport) //Teleport forbidden return 0; - do{ + do { x=rnd()%(map[m].xs-2)+1; y=rnd()%(map[m].ys-2)+1; - }while(iMap->getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 ); + } while( iMap->getcell(m,x,y,CELL_CHKNOPASS) && (i++) < 1000 ); if (i < 1000) - return pc->setpos(sd,map[sd->bl.m].index,x,y,type); + return pc->setpos(sd,map_id2index(sd->bl.m),x,y,type); return 0; } -- cgit v1.2.3-60-g2f50