diff options
author | Haru <haru@dotalux.com> | 2016-04-05 13:15:04 +0200 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2016-04-05 13:15:04 +0200 |
commit | 187c0b6b288a6a4267aeb949e054dd8fabde6627 (patch) | |
tree | c3bbb6a5999659f2da840563fa6f46a517677145 | |
parent | 73a617651b290eef4d5c1e6900eed6cb3526c307 (diff) | |
parent | c3eb11ff4c048a5ff6770dc57659ed7798576a97 (diff) | |
download | hercules-187c0b6b288a6a4267aeb949e054dd8fabde6627.tar.gz hercules-187c0b6b288a6a4267aeb949e054dd8fabde6627.tar.bz2 hercules-187c0b6b288a6a4267aeb949e054dd8fabde6627.tar.xz hercules-187c0b6b288a6a4267aeb949e054dd8fabde6627.zip |
Merge pull request #1237 from 4144/mapchecks
Add missing checks into some files in map server
-rw-r--r-- | src/map/map.c | 114 | ||||
-rw-r--r-- | src/map/mapreg_sql.c | 7 | ||||
-rw-r--r-- | src/map/mercenary.c | 17 | ||||
-rw-r--r-- | src/map/mob.c | 95 | ||||
-rw-r--r-- | src/map/npc.c | 156 |
5 files changed, 354 insertions, 35 deletions
diff --git a/src/map/map.c b/src/map/map.c index aa4c2d84c..3a7d752c3 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -193,6 +193,7 @@ void map_update_cell_bl( struct block_list *bl, bool increase ) { #ifdef CELL_NOSTACK int pos; + nullpo_retv(bl); if( bl->m < 0 || bl->x < 0 || bl->x >= map->list[bl->m].xs || bl->y < 0 || bl->y >= map->list[bl->m].ys || !(bl->type&BL_CHAR) ) @@ -309,9 +310,14 @@ int map_delblock(struct block_list* bl) * (which are executed by default on BL_CHAR types) *------------------------------------------*/ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) { - int x0 = bl->x, y0 = bl->y; struct status_change *sc = NULL; - int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE); + int x0, y0; + int moveblock; + + nullpo_ret(bl); + x0 = bl->x; + y0 = bl->y; + moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE); if (!bl->prev) { //Block not in map, just update coordinates, but do naught else. @@ -477,6 +483,8 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x, int16 m,bx,by; struct block_list *bl; struct skill_unit *su; + + nullpo_retr(NULL, target); m = target->m; if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys)) @@ -854,6 +862,9 @@ static int bl_vgetall_inshootrange(struct block_list *bl, va_list args) struct block_list *center = va_arg(args, struct block_list*); #ifdef CIRCULAR_AREA int range = va_arg(args, int); + nullpo_ret(center); + nullpo_ret(bl); + if (!check_distance_bl(center, bl, range)) return 0; #endif @@ -1041,6 +1052,9 @@ static int bl_vgetall_inmovearea(struct block_list *bl, va_list args) struct block_list *center = va_arg(args, struct block_list*); int range = va_arg(args, int); + nullpo_ret(bl); + nullpo_ret(center); + if ((dx > 0 && bl->x < center->x - range + dx) || (dx < 0 && bl->x > center->x + range + dx) || (dy > 0 && bl->y < center->y - range + dy) || @@ -1203,11 +1217,15 @@ static int bl_vgetall_inpath(struct block_list *bl, va_list args) int len_limit = va_arg(args, int); int magnitude2 = va_arg(args, int); - int xi = bl->x; - int yi = bl->y; + int xi; + int yi; int xu, yu; + int k; - int k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 ); + nullpo_ret(bl); + xi = bl->x; + yi = bl->y; + k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 ); if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well. return 0; @@ -1422,6 +1440,9 @@ int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16 int free_cell,i,j; int free_cells[9][2]; + nullpo_ret(x); + nullpo_ret(y); + for(free_cell=0,i=-1;i<=1;i++){ if(i+*y<0 || i+*y>=map->list[m].ys) continue; @@ -1468,6 +1489,9 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 int rx2 = 2*rx+1; int ry2 = 2*ry+1; + nullpo_ret(x); + nullpo_ret(y); + if( !src && (!(flag&1) || flag&2) ) { ShowDebug("map_search_freecell: Incorrect usage! When src is NULL, flag has to be &1 and can't have &2\n"); @@ -1478,6 +1502,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 bx = *x; by = *y; } else { + nullpo_ret(src); bx = src->x; by = src->y; m = src->m; @@ -1534,10 +1559,15 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag) { uint8 dir = 6; - int16 tx = *x; - int16 ty = *y; + int16 tx; + int16 ty; int costrange = 10; + nullpo_ret(x); + nullpo_ret(y); + tx = *x; + ty = *y; + if(!map->count_oncell(m, tx, ty, type, flag)) return true; //Current cell is free @@ -1794,6 +1824,8 @@ void map_deliddb(struct block_list *bl) int map_quit(struct map_session_data *sd) { int i; + nullpo_ret(sd); + if(!sd->state.active) { //Removing a player that is not active. struct auth_node *node = chrif->search(sd->status.account_id); if (node && node->char_id == sd->status.char_id && @@ -2547,6 +2579,7 @@ bool map_addnpc(int16 m,struct npc_data *nd) { // Returns the index of successful, or -1 if the list was full. int map_addmobtolist(unsigned short m, struct spawn_data *spawn) { int i; + nullpo_retr(-1, spawn); ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map->list[m].moblist[i] == NULL ); if( i < MAX_MOB_LIST_PER_MAP ) { map->list[m].moblist[i] = spawn; @@ -2628,6 +2661,7 @@ int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) { } void map_removemobs(int16 m) { + Assert_retv(m >= 0 && m < map->count); if (map->list[m].mob_delete_timer != INVALID_TIMER) // should never happen return; //Mobs are already scheduled for removal @@ -2662,6 +2696,8 @@ int16 map_mapindex2mapid(unsigned short map_index) { int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) { struct map_data_other_server *mdos; + nullpo_retr(-1, ip); + nullpo_retr(-1, port); mdos = (struct map_data_other_server*)uidb_get(map->map_db,(unsigned int)name); if(mdos==NULL || mdos->cell) //If gat isn't null, this is a local map. return -1; @@ -2737,11 +2773,19 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y) *------------------------------------------*/ int map_random_dir(struct block_list *bl, int16 *x, int16 *y) { - short xi = *x-bl->x; - short yi = *y-bl->y; + short xi; + short yi; short i=0; - int dist2 = xi*xi + yi*yi; - short dist = (short)sqrt((float)dist2); + int dist2; + short dist; + + nullpo_ret(bl); + nullpo_ret(x); + nullpo_ret(y); + xi = *x-bl->x; + yi = *y-bl->y; + dist2 = xi*xi + yi*yi; + dist = (short)sqrt((float)dist2); if (dist < 1) dist =1; @@ -2794,7 +2838,10 @@ int map_cell2gat(struct mapcell cell) { return 1; // default to 'wall' } void map_cellfromcache(struct map_data *m) { - struct map_cache_map_info *info = (struct map_cache_map_info *)m->cellPos; + struct map_cache_map_info *info; + + nullpo_retv(m); + info = (struct map_cache_map_info *)m->cellPos; if (info) { char decode_buffer[MAX_MAP_SIZE]; @@ -2897,6 +2944,7 @@ int map_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 /* [Ind/Hercules] */ int map_sub_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) { + nullpo_ret(m); map->cellfromcache(m); m->getcellp = map->getcellp; m->setcell = map->setcell; @@ -2963,6 +3011,9 @@ void map_setgatcell(int16 m, int16 x, int16 y, int gat) { *------------------------------------------*/ void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1) { + nullpo_retv(x1); + nullpo_retv(y1); + if( dir == 0 || dir == 4 ) *x1 = x; // Keep X else if( dir > 0 && dir < 4 ) @@ -3029,6 +3080,8 @@ void map_iwall_get(struct map_session_data *sd) int16 x1, y1; int i; + nullpo_retv(sd); + if( map->list[sd->bl.m].iwall_num < 1 ) return; @@ -3107,6 +3160,7 @@ int map_setipport(unsigned short map_index, uint32 ip, uint16 port) int map_eraseallipport_sub(union DBKey key, struct DBData *data, va_list va) { struct map_data_other_server *mdos = DB->data2ptr(data); + nullpo_ret(mdos); if(mdos->cell == NULL) { db_remove(map->map_db,key); aFree(mdos); @@ -3193,6 +3247,9 @@ int map_readfromcache(struct map_data *m, char *buffer) { struct map_cache_map_info *info = NULL; char *p = buffer + sizeof(struct map_cache_main_header); + nullpo_ret(m); + nullpo_ret(buffer); + for(i = 0; i < header->map_count; i++) { info = (struct map_cache_map_info *)p; @@ -3234,6 +3291,7 @@ int map_addmap(const char* mapname) { } void map_delmapid(int id) { + Assert_retv(id >= 0 && id < map->count); ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map->list[id].name); memmove(map->list+id, map->list+id+1, sizeof(map->list[0])*(map->count-id-1)); map->count--; @@ -3243,6 +3301,7 @@ int map_delmap(char* mapname) { int i; char map_name[MAP_NAME_LENGTH]; + nullpo_ret(mapname); if (strcmpi(mapname, "all") == 0) { map->count = 0; return 0; @@ -3264,6 +3323,8 @@ int map_delmap(char* mapname) { void map_zone_clear_single(struct map_zone_data *zone) { int i; + nullpo_retv(zone); + for(i = 0; i < zone->disabled_skills_count; i++) { aFree(zone->disabled_skills[i]); } @@ -3321,6 +3382,7 @@ void map_zone_db_clear(void) } void map_clean(int i) { int v; + Assert_retv(i >= 0 && i < map->count); if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map->list[i].cell); if(map->list[i].block) aFree(map->list[i].block); if(map->list[i].block_mob) aFree(map->list[i].block_mob); @@ -3519,6 +3581,7 @@ int map_waterheight(char* mapname) char fn[256]; char *rsw, *found; + nullpo_retr(NO_WATER, mapname); //Look up for the rsw snprintf(fn, sizeof(fn), "data\\%s.rsw", mapname); @@ -3547,6 +3610,7 @@ int map_readgat (struct map_data* m) int water_height; size_t xy, off, num_cells; + nullpo_ret(m); sprintf(filename, "data\\%s.gat", m->name); gat = (uint8 *) grfio_read(filename); @@ -3584,10 +3648,12 @@ int map_readgat (struct map_data* m) * Add/Remove map to the map_db *--------------------------------------*/ void map_addmap2db(struct map_data *m) { + nullpo_retv(m); map->index2mapid[m->index] = m->m; } void map_removemapdb(struct map_data *m) { + nullpo_retv(m); map->index2mapid[m->index] = -1; } @@ -3692,6 +3758,8 @@ int map_config_read(char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; + nullpo_retr(1, cfgName); + fp = fopen(cfgName,"r"); if( fp == NULL ) { ShowError("Map configuration file not found at: %s\n", cfgName); @@ -3786,6 +3854,7 @@ int map_config_read_sub(char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; + nullpo_retr(1, cfgName); fp = fopen(cfgName,"r"); if (fp == NULL) { ShowError("Map configuration file not found at: %s\n", cfgName); @@ -3823,6 +3892,7 @@ void map_reloadnpc_sub(char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; + nullpo_retv(cfgName); fp = fopen(cfgName,"r"); if (fp == NULL) { ShowError("Map configuration file not found at: %s\n", cfgName); @@ -3884,6 +3954,7 @@ int inter_config_read(char *cfgName) { char line[1024],w1[1024],w2[1024]; FILE *fp; + nullpo_retr(1, cfgName); if (!(fp = fopen(cfgName,"r"))) { ShowError("File not found: %s\n",cfgName); return 1; @@ -3981,6 +4052,9 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone struct map_zone_data *zone = NULL; int cursor, i, j; + nullpo_retr(NULL, main); + nullpo_retr(NULL, other); + sprintf(newzone, "%s+%s",main->name,other->name); if( (zone = strdb_get(map->zone_db, newzone)) ) @@ -4074,6 +4148,7 @@ void map_zone_change2(int m, struct map_zone_data *zone) { const char *empty = ""; + Assert_retv(m >= 0 && m < map->count); if( map->list[m].zone == zone ) return; @@ -4091,6 +4166,7 @@ void map_zone_change2(int m, struct map_zone_data *zone) } /* when changing from a mapflag to another during runtime */ void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) { + Assert_retv(m >= 0 && m < map->count); map->list[m].prev_zone = map->list[m].zone; if( map->list[m].zone_mf_count ) @@ -4103,6 +4179,7 @@ void map_zone_remove(int m) char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH]; unsigned short k; const char *empty = ""; + Assert_retv(m >= 0 && m < map->count); for(k = 0; k < map->list[m].zone_mf_count; k++) { size_t len = strlen(map->list[m].zone_mf[k]),j; params[0] = '\0'; @@ -4125,6 +4202,7 @@ void map_zone_remove(int m) map->list[m].zone_mf_count = 0; } static inline void map_zone_mf_cache_add(int m, char *rflag) { + Assert_retv(m >= 0 && m < map->count); RECREATE(map->list[m].zone_mf, char *, ++map->list[m].zone_mf_count); CREATE(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH); safestrncpy(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], rflag, MAP_ZONE_MAPFLAG_LENGTH); @@ -4135,6 +4213,10 @@ bool map_zone_mf_cache(int m, char *flag, char *params) { char rflag[MAP_ZONE_MAPFLAG_LENGTH]; int state = 1; + nullpo_retr(false, flag); + nullpo_retr(false, params); + Assert_retr(false, m >= 0 && m < map->count); + if (params[0] != '\0' && !strcmpi(params, "off")) state = 0; @@ -4831,6 +4913,8 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const int i; const char *empty = ""; char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH]; + Assert_retv(m >= 0 && m < map->count); + nullpo_retv(zone); map->list[m].zone = zone; for(i = 0; i < zone->mapflags_count; i++) { size_t len = strlen(zone->mapflags[i]); @@ -4941,8 +5025,9 @@ unsigned short map_zone_str2skillid(const char *name) { enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *subtype) { char temp[200], *parse; enum bl_type bl = BL_NUL; - *subtype = MZS_NONE; + nullpo_retr(BL_NUL, subtype); + *subtype = MZS_NONE; if( !entry ) return BL_NUL; @@ -5416,6 +5501,8 @@ int map_get_new_bonus_id (void) { void map_add_questinfo(int m, struct questinfo *qi) { unsigned short i; + nullpo_retv(qi); + Assert_retv(m >= 0 && m < map->count); /* duplicate, override */ for(i = 0; i < map->list[m].qi_count; i++) { if( map->list[m].qi_data[i].nd == qi->nd ) @@ -5431,6 +5518,7 @@ void map_add_questinfo(int m, struct questinfo *qi) { bool map_remove_questinfo(int m, struct npc_data *nd) { unsigned short i; + Assert_retr(false, m >= 0 && m < map->count); for(i = 0; i < map->list[m].qi_count; i++) { struct questinfo *qi = &map->list[m].qi_data[i]; if( qi->nd == nd ) { diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 8a8f9f309..82ce39d64 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -28,6 +28,7 @@ #include "common/db.h" #include "common/ers.h" #include "common/memmgr.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/sql.h" #include "common/strlib.h" @@ -76,6 +77,7 @@ bool mapreg_setreg(int64 uid, int val) { unsigned int i = script_getvaridx(uid); const char* name = script->get_str(num); + nullpo_retr(true, name); if( val != 0 ) { if( (m = i64db_get(mapreg->regs.vars, uid)) ) { m->u.i = val; @@ -132,6 +134,8 @@ bool mapreg_setregstr(int64 uid, const char* str) { unsigned int i = script_getvaridx(uid); const char* name = script->get_str(num); + nullpo_retr(true, name); + if( str == NULL || *str == 0 ) { if( i ) script->array_update(&mapreg->regs, uid, true); @@ -246,6 +250,7 @@ void script_save_mapreg(void) int num = script_getvarid(m->uid); int i = script_getvaridx(m->uid); const char* name = script->get_str(num); + nullpo_retv(name); if (!m->is_string) { if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, m->u.i, name, i) ) Sql_ShowDebug(map->mysql_handle); @@ -346,6 +351,8 @@ void mapreg_init(void) { * Loads the mapreg configuration file. */ bool mapreg_config_read(const char* w1, const char* w2) { + nullpo_retr(false, w1); + nullpo_retr(false, w2); if(!strcmpi(w1, "mapreg_db")) safestrncpy(mapreg->table, w2, sizeof(mapreg->table)); else diff --git a/src/map/mercenary.c b/src/map/mercenary.c index fa337e13b..0b055bedf 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -234,6 +234,7 @@ int mercenary_set_calls(struct mercenary_data *md, int value) int mercenary_save(struct mercenary_data *md) { + nullpo_retr(1, md); md->mercenary.hp = md->battle_status.hp; md->mercenary.sp = md->battle_status.sp; md->mercenary.life_time = mercenary->get_lifetime(md); @@ -265,7 +266,10 @@ int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) { int merc_delete(struct mercenary_data *md, int reply) { - struct map_session_data *sd = md->master; + struct map_session_data *sd; + + nullpo_retr(0, md); + sd = md->master; md->mercenary.life_time = 0; mercenary->contract_stop(md); @@ -299,6 +303,7 @@ void merc_contract_stop(struct mercenary_data *md) void merc_contract_init(struct mercenary_data *md) { + nullpo_retv(md); if( md->contract_timer == INVALID_TIMER ) md->contract_timer = timer->add(timer->gettick() + md->mercenary.life_time, mercenary->contract_end_timer, md->master->bl.id, 0); @@ -310,8 +315,10 @@ int merc_data_received(const struct s_mercenary *merc, bool flag) struct map_session_data *sd; struct mercenary_data *md; struct s_mercenary_db *db; - int i = mercenary->search_index(merc->class_); + int i; + nullpo_ret(merc); + i = mercenary->search_index(merc->class_); if( (sd = map->charid2sd(merc->char_id)) == NULL ) return 0; if (!flag || i == INDEX_NOT_FOUND) { @@ -370,6 +377,7 @@ int merc_data_received(const struct s_mercenary *merc, bool flag) void mercenary_heal(struct mercenary_data *md, int hp, int sp) { + nullpo_retv(md); if( hp ) clif->mercenary_updatestatus(md->master, SP_HP); if( sp ) @@ -387,12 +395,14 @@ int mercenary_killbonus(struct mercenary_data *md) const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT }; int index = rnd() % ARRAYLENGTH(scs); + nullpo_ret(md); sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000); return 0; } int mercenary_kills(struct mercenary_data *md) { + nullpo_ret(md); md->mercenary.kill_count++; md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); @@ -425,6 +435,8 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) { struct s_mercenary_db *db; struct status_data *mstatus; + nullpo_retr(false, str); + Assert_retr(false, current >= 0 && current < MAX_MERCENARY_CLASS); db = &mercenary->db[current]; db->class_ = atoi(str[0]); safestrncpy(db->sprite, str[1], NAME_LENGTH); @@ -486,6 +498,7 @@ bool read_mercenary_skilldb_sub(char* str[], int columns, int current) int i, class_; uint16 skill_id, skill_lv; + nullpo_retr(false, str); class_ = atoi(str[0]); ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary->db[i].class_); if( i == MAX_MERCENARY_CLASS ) diff --git a/src/map/mob.c b/src/map/mob.c index 53ad87912..c765e7d63 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -114,6 +114,8 @@ struct mob_chat *mob_chat(short id) { int mobdb_searchname(const char *str) { int i; + + nullpo_ret(str); for(i=0;i<=MAX_MOB_DB;i++){ struct mob_db *monster = mob->db(i); if(monster == mob->dummy) //Skip dummy mobs. @@ -129,10 +131,13 @@ int mobdb_searchname(const char *str) return 0; } int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag) { + + nullpo_ret(monster); if (monster == mob->dummy) return 1; if(!monster->base_exp && !monster->job_exp && monster->spawn[0].qty < 1) return 1; // Monsters with no base/job exp and no spawn point are, by this criteria, considered "slave mobs" and excluded from search results + nullpo_ret(str); if( !flag ) { if(stristr(monster->jname,str)) return 0; @@ -156,6 +161,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) { struct npc_data *nd; + nullpo_retv(md); if ( md->tomb_nid ) mob->mvptomb_destroy(md); @@ -181,6 +187,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) void mvptomb_destroy(struct mob_data *md) { struct npc_data *nd; + nullpo_retv(md); if ( (nd = map->id2nd(md->tomb_nid)) ) { int16 m, i; @@ -212,6 +219,7 @@ int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int { int count = 0, i; struct mob_db* monster; + nullpo_ret(data); for(i=0;i<=MAX_MOB_DB;i++){ monster = mob->db(i); if (monster == mob->dummy || mob->is_clone(i) ) //keep clones out (or you leak player stats) @@ -253,6 +261,7 @@ int mob_parse_dataset(struct spawn_data *data) { size_t len; + nullpo_ret(data); if ((!mob->db_checkid(data->class_) && !mob->is_clone(data->class_)) || !data->num) return 0; @@ -276,6 +285,7 @@ int mob_parse_dataset(struct spawn_data *data) *------------------------------------------*/ struct mob_data* mob_spawn_dataset(struct spawn_data *data) { struct mob_data *md = NULL; + nullpo_retr(NULL, data); CREATE(md, struct mob_data, 1); md->bl.id= npc->get_new_npc_id(); md->bl.type = BL_MOB; @@ -328,6 +338,7 @@ int mob_get_random_id(int type, int flag, int lv) ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type); return 0; } + Assert_ret(type >= 0 && type < MAX_RANDOMMONSTER); do { if (type) class_ = summon[type].class_[rnd()%summon[type].qty]; @@ -634,6 +645,11 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam struct guild *g=NULL; struct guild_castle *gc; int16 m; + + nullpo_ret(mapname); + nullpo_ret(mobname); + nullpo_ret(event); + memset(&data, 0, sizeof(struct spawn_data)); data.num = 1; @@ -728,6 +744,10 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int struct spawn_data data; int16 m; + nullpo_ret(mapname); + nullpo_ret(mobname); + nullpo_ret(event); + if( (m = map->mapname2mapid(mapname)) < 0 ) { ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname); return 0; @@ -846,6 +866,8 @@ int mob_setdelayspawn(struct mob_data *md) uint32 mode; struct mob_db *db; + nullpo_ret(md); + if (!md->spawn) //Doesn't has respawn data! return unit->free(&md->bl,CLR_DEAD); @@ -903,6 +925,7 @@ int mob_spawn (struct mob_data *md) int64 tick = timer->gettick(); int64 c = 0; + nullpo_retr(1, md); md->last_thinktime = tick; if (md->bl.prev != NULL) unit->remove_map(&md->bl,CLR_RESPAWN,ALC_MARK); @@ -992,6 +1015,8 @@ int mob_spawn (struct mob_data *md) *------------------------------------------*/ int mob_can_changetarget(const struct mob_data *md, const struct block_list *target, uint32 mode) { + nullpo_ret(md); + nullpo_ret(target); // if the monster was provoked ignore the above rule [celest] if(md->state.provoke_flag) { @@ -1057,6 +1082,8 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap) md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); mode = va_arg(ap, uint32); + nullpo_ret(md); + nullpo_ret(target); //If can't seek yet, not an enemy, or you can't attack it, skip. if (md->bl.id == bl->id || (*target) == bl || !status->check_skilluse(&md->bl, bl, 0, 0)) @@ -1111,8 +1138,10 @@ int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) { struct block_list **target; nullpo_ret(bl); - md=va_arg(ap,struct mob_data *); - target= va_arg(ap,struct block_list**); + md = va_arg(ap,struct mob_data *); + target = va_arg(ap,struct block_list**); + nullpo_ret(md); + nullpo_ret(target); //If can't seek yet, not an enemy, or you can't attack it, skip. if( md->bl.id == bl->id || *target == bl @@ -1139,6 +1168,8 @@ int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) { nullpo_ret(bl); md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); + nullpo_retr(1, md); + nullpo_retr(1, target); if( status->check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) { (*target) = bl; @@ -1157,6 +1188,8 @@ int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); + nullpo_ret(md); + nullpo_ret(target); dist=distance_bl(&md->bl, bl); if(mob->can_reach(md,bl,dist+1, MSS_LOOT) && @@ -1177,6 +1210,9 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) { struct npc_data *nd = NULL; nullpo_ret(bl); + nullpo_ret(target); + nullpo_ret(target_nd); + nullpo_ret(min_distance); Assert_ret(bl->type == BL_NPC); nd = BL_UCAST(BL_NPC, bl); @@ -1201,6 +1237,7 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) { int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) { struct block_list *bl; + nullpo_ret(md); bl=map->id2bl(md->master_id); if (!bl || status->isdead(bl)) { @@ -1378,6 +1415,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) { struct npc_data *warp = NULL; int distance = AREA_SIZE; + nullpo_ret(md); if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1)) return 0; //Can't warp chase. @@ -1405,6 +1443,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { uint32 mode; int view_range, can_move; + nullpo_retr(false, md); if(md->bl.prev == NULL || md->status.hp <= 0) return false; @@ -1702,6 +1741,7 @@ int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap) *------------------------------------------*/ int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { int64 tick; + nullpo_ret(sd); tick=va_arg(ap, int64); map->foreachinrange(mob->ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); @@ -1810,7 +1850,10 @@ struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) { *------------------------------------------*/ struct item_drop* mob_setlootitem(struct item* item) { - struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); + struct item_drop *drop ; + + nullpo_retr(NULL, item); + drop = ers_alloc(item_drop_ers, struct item_drop); memcpy(&drop->item_data, item, sizeof(struct item)); drop->next = NULL; return drop; @@ -1847,6 +1890,9 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite { struct map_session_data *sd = NULL; + nullpo_retv(md); + nullpo_retv(dlist); + nullpo_retv(ditem); //Logs items, dropped by mobs [Lupus] logs->pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data, NULL); @@ -1932,6 +1978,9 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) { int char_id = 0, flag = MDLF_NORMAL; + nullpo_retv(md); + nullpo_retv(src); + if( damage < 0 ) return; //Do nothing for absorbed damage. if( !damage && !(src->type&DEFAULT_ENEMY_TYPE(md)) ) @@ -2042,6 +2091,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) } //Call when a mob has received damage. void mob_damage(struct mob_data *md, struct block_list *src, int damage) { + nullpo_retv(md); if (damage > 0) { //Store total damage... if (UINT_MAX - (unsigned int)damage > md->tdmg) md->tdmg+=damage; @@ -2105,12 +2155,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { int id,zeny; unsigned int base_exp,job_exp; } pt[DAMAGELOG_SIZE] = { { 0 } }; - int i, temp, count, m = md->bl.m; + int i, temp, count, m; int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are eligible for exp distribution unsigned int mvp_damage; int64 tick = timer->gettick(); bool rebirth, homkillonly; + nullpo_retr(3, md); + m = md->bl.m; mstatus = &md->status; if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) @@ -2663,6 +2715,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { void mob_revive(struct mob_data *md, unsigned int hp) { int64 tick = timer->gettick(); + + nullpo_retv(md); md->state.skillstate = MSS_IDLE; md->last_thinktime = tick; md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME; @@ -2810,6 +2864,7 @@ int mob_class_change (struct mob_data *md, int class_) { *------------------------------------------*/ void mob_heal(struct mob_data *md, unsigned int heal) { + nullpo_retv(md); if (battle_config.show_mob_info&3) clif->charnameack (0, &md->bl); #if PACKETVER >= 20131223 @@ -2844,6 +2899,7 @@ int mob_warpslave_sub(struct block_list *bl, va_list ap) range = va_arg(ap, int); nullpo_ret(bl); + nullpo_ret(master); Assert_ret(bl->type == BL_MOB); md = BL_UCAST(BL_MOB, bl); @@ -2861,6 +2917,7 @@ int mob_warpslave_sub(struct block_list *bl, va_list ap) * appear in randomly. *------------------------------------------*/ int mob_warpslave(struct block_list *bl, int range) { + nullpo_ret(bl); if (range < 1) range = 1; //Min range needed to avoid crashes and stuff. [Skotlex] @@ -2888,6 +2945,7 @@ int mob_countslave_sub(struct block_list *bl, va_list ap) * Counts the number of slaves a mob has on the map. *------------------------------------------*/ int mob_countslave(struct block_list *bl) { + nullpo_ret(bl); return map->foreachinmap(mob->countslave_sub, bl->m, BL_MOB,bl->id); } @@ -3016,6 +3074,8 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap) struct mob_data *md; md = va_arg(ap,struct mob_data *); + nullpo_ret(bl); + nullpo_ret(md); min_rate=va_arg(ap,int); max_rate=va_arg(ap,int); fr=va_arg(ap,struct block_list **); @@ -3326,6 +3386,8 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag) { int target_id, res = 0; + nullpo_ret(md); + nullpo_ret(src); if(md->bl.prev == NULL || md->status.hp <= 0) return 0; @@ -3387,7 +3449,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons return 0; ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL ); - if(class_ >= MOB_CLONE_END) + if(class_ < 0 || class_ >= MOB_CLONE_END) return 0; db = mob->db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db)); @@ -3577,7 +3639,10 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons int mob_clone_delete(struct mob_data *md) { - const int class_ = md->class_; + int class_; + + nullpo_ret(md); + class_ = md->class_; if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END && mob->db_data[class_]!=NULL) { mob->destroy_mob_db(class_); @@ -3667,6 +3732,7 @@ unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_ */ void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) { + nullpo_retv(rate_adjust); if( item_drop_ratio_db[nameid] ) { if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs int i; @@ -3701,6 +3767,7 @@ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int va void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t) { int i32; + nullpo_retv(entry); if (mob->lookup_const(t, "Str", &i32) && i32 >= 0) { entry->status.str = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } @@ -3784,6 +3851,7 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t) int idx = 0; int i32; + nullpo_retv(entry); while (idx < MAX_MVP_DROP && (drop = libconfig->setting_get_elem(t, i))) { const char *name = config_setting_name(drop); int rate_adjust = battle_config.item_rate_mvp; @@ -3841,6 +3909,7 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t) int i32; int k; + nullpo_retv(entry); while (idx < MAX_MOB_DROP && (drop = libconfig->setting_get_elem(t, i))) { const char *name = config_setting_name(drop); int rate_adjust, type; @@ -3962,6 +4031,7 @@ int mob_db_validate_entry(struct mob_db *entry, int n, const char *source) { struct mob_data data; + nullpo_ret(entry); if (entry->mob_id <= 1000 || entry->mob_id > MAX_MOB_DB) { ShowError("mob_db_validate_entry: Invalid monster ID %d, must be in range %d-%d.\n", entry->mob_id, 1000, MAX_MOB_DB); return 0; @@ -4395,6 +4465,8 @@ bool mob_lookup_const(const struct config_setting_t *it, const char *name, int * bool mob_get_const(const struct config_setting_t *it, int *value) { const char *str = config_setting_get_string(it); + + nullpo_retr(false, value); if (str && *str && script->get_constant(str, value)) return true; @@ -4491,6 +4563,7 @@ bool mob_readdb_mobavail(char* str[], int columns, int current) { int class_, k; + nullpo_retr(false, str); class_=atoi(str[0]); if(mob->db(class_) == mob->dummy) { @@ -4602,6 +4675,8 @@ bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_ms int msg_id; size_t len; + nullpo_retr(false, str); + nullpo_retr(false, last_msg_id); msg_id = atoi(str[0]); if (msg_id <= 0 || msg_id > MAX_MOB_CHAT) @@ -4786,6 +4861,7 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current) int i =0, j, tmp; uint16 sidx = 0; + nullpo_retr(false, str); mob_id = atoi(str[0]); if (mob_id > 0 && mob->db(mob_id) == mob->dummy) @@ -5001,6 +5077,7 @@ bool mob_readdb_race2(char* fields[], int columns, int current) { int race, i; + nullpo_retr(false, fields); race = atoi(fields[0]); if (race < RC2_NONE || race >= RC2_MAX) { @@ -5025,6 +5102,8 @@ bool mob_readdb_race2(char* fields[], int columns, int current) bool mob_readdb_itemratio(char* str[], int columns, int current) { int nameid, ratio, i; + + nullpo_retr(false, str); nameid = atoi(str[0]); if( itemdb->exists(nameid) == NULL ) @@ -5126,7 +5205,9 @@ int do_init_mob(bool minimal) { void mob_destroy_mob_db(int index) { - struct mob_db *data = mob->db_data[index]; + struct mob_db *data; + Assert_retv(index >= 0 && index <= MAX_MOB_DB); + data = mob->db_data[index]; HPM->data_store_destroy(&data->hdata); aFree(data); mob->db_data[index] = NULL; diff --git a/src/map/npc.c b/src/map/npc.c index 4db5ce625..1b784b0c8 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -177,6 +177,7 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_retr(1, nd); if( nd->touching_id ) return 0; // Attached a player already. Can't trigger on anyone else. @@ -191,6 +192,8 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_retr(1, sd); + nullpo_retr(1, nd); if (sd->areanpc_id == nd->bl.id) return 0; @@ -202,6 +205,8 @@ int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_ret(sd); + nullpo_ret(nd); if (sd->areanpc_id != nd->bl.id) return 0; @@ -381,8 +386,12 @@ struct DBData npc_event_export_create(union DBKey key, va_list args) *------------------------------------------*/ int npc_event_export(struct npc_data *nd, int i) { - char* lname = nd->u.scr.label_list[i].name; - int pos = nd->u.scr.label_list[i].pos; + char* lname; + int pos; + nullpo_ret(nd); + Assert_ret(i >= 0 && i < nd->u.scr.label_list_num); + lname = nd->u.scr.label_list[i].name; + pos = nd->u.scr.label_list[i].pos; if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) { struct event_data *ev; struct linkdb_node **label_linkdb = NULL; @@ -435,6 +444,7 @@ void npc_event_doall_sub(void *key, void *data, va_list ap) // runs the specified event (supports both single-npc and global events) int npc_event_do(const char* name) { + nullpo_ret(name); if( name[0] == ':' && name[1] == ':' ) { return npc->event_doall(name+2); // skip leading "::" } @@ -539,9 +549,12 @@ void npc_event_do_oninit( bool reload ) int npc_timerevent_export(struct npc_data *nd, int i) { int t = 0, len = 0; - char *lname = nd->u.scr.label_list[i].name; - int pos = nd->u.scr.label_list[i].pos; - if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && lname[len] == '\0') { + char *lname; + int pos; + nullpo_ret(nd); + lname = nd->u.scr.label_list[i].name; + pos = nd->u.scr.label_list[i].pos; + if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && len < NAME_LENGTH && lname[len] == '\0') { // Timer event struct npc_timerevent_list *te = nd->u.scr.timer_event; int j, k = nd->u.scr.timeramount; @@ -581,6 +594,8 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data) struct timer_event_data *ted = (struct timer_event_data*)data; struct map_session_data *sd=NULL; + nullpo_ret(ted); + if( nd == NULL ) { ShowError("npc_timerevent: NPC not found??\n"); return 0; @@ -733,6 +748,7 @@ void npc_timerevent_quit(struct map_session_data* sd) struct npc_data* nd; struct timer_event_data *ted; + nullpo_retv(sd); // Check timer existence if( sd->npc_timer_id == INVALID_TIMER ) return; @@ -764,6 +780,7 @@ void npc_timerevent_quit(struct map_session_data* sd) { int old_rid,old_timer; int64 old_tick; + nullpo_retv(ted); //Set timer related info. old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. @@ -832,6 +849,8 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer) int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname) { + nullpo_retr(2, sd); + nullpo_retr(2, eventname); if ( sd->npc_id != 0 ) { //Enqueue the event trigger. @@ -916,9 +935,11 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) { * If not, it unsets it and searches for another player in range. *------------------------------------------*/ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) { - struct npc_data *nd = map->id2nd(sd->touching_id); + struct npc_data *nd; short xs, ys; + nullpo_retr(1, sd); + nd = map->id2nd(sd->touching_id); if( !nd || nd->touching_id != sd->bl.id ) return 1; @@ -950,7 +971,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) int j, found_warp = 0; nullpo_retr(1, sd); - + Assert_retr(1, m >= 0 && m < map->count); #if 0 // Why not enqueue it? [Inkfish] if(sd->npc_id) return 1; @@ -1035,6 +1056,7 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) { struct npc_data *nd = NULL; nullpo_retr(1, sd); + Assert_retr(1, m >= 0 && m < map->count); if (!sd->areanpc_id) return 0; @@ -1054,11 +1076,16 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) // Return 1 if Warped int npc_touch_areanpc2(struct mob_data *md) { - int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id; + int i, m, x, y, id; char eventname[EVENT_NAME_LENGTH]; struct event_data* ev; int xs, ys; + nullpo_ret(md); + m = md->bl.m; + x = md->bl.x; + y = md->bl.y; + for( i = 0; i < map->list[m].npc_num; i++ ) { if( map->list[m].npc[i]->option&OPTION_INVISIBLE ) continue; @@ -1117,6 +1144,8 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { int x0,y0,x1,y1; int xs,ys; + Assert_retr(1, m >= 0 && m < map->count); + if (range < 0) return 0; x0 = max(x-range, 0); y0 = max(y-range, 0); @@ -1188,6 +1217,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b if (distance > nd->area_size) distance = nd->area_size; + nullpo_retr(NULL, bl); if (bl->m != sd->bl.m || bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance || bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance) @@ -1209,6 +1239,9 @@ int npc_globalmessage(const char* name, const char* mes) if (!nd) return 0; + nullpo_ret(name); + nullpo_ret(mes); + snprintf(temp, sizeof(temp), "%s : %s", name, mes); clif->GlobalMessage(&nd->bl,temp); @@ -1220,6 +1253,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd) { char buffer[200]; char time[10]; + nullpo_retv(nd); strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time)); // TODO: Find exact color? @@ -1394,6 +1428,8 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlis struct npc_item_list *shop = NULL; unsigned short shop_size = 0; + nullpo_retr(ERROR_TYPE_SYSTEM, sd); + nullpo_retr(ERROR_TYPE_SYSTEM, item_list); if( sd->state.trading ) return ERROR_TYPE_EXCHANGE; @@ -1493,6 +1529,9 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str int key_nameid = 0; int key_amount = 0; + nullpo_ret(item_list); + nullpo_ret(nd); + // discard old contents script->cleararray_pc(sd, "@bought_nameid", (void*)0); script->cleararray_pc(sd, "@bought_quantity", (void*)0); @@ -1567,6 +1606,8 @@ void npc_market_fromsql(void) * Saves persistent NPC Market Data into SQL **/ void npc_market_tosql(struct npc_data *nd, unsigned short index) { + nullpo_retv(nd); + Assert_retv(index < nd->u.scr.shop->items); if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%u')", map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty)) Sql_ShowDebug(map->mysql_handle); @@ -1588,12 +1629,16 @@ void npc_market_delfromsql_sub(const char *npcname, unsigned short index) { * Removes persistent NPC Market Data from SQL **/ void npc_market_delfromsql(struct npc_data *nd, unsigned short index) { + nullpo_retv(nd); + Assert_retv(index == USHRT_MAX || index < nd->u.scr.shop->items); npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid); } /** * Judges whether to allow and spawn a trader's window. **/ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { + nullpo_retr(false, sd); + nullpo_retr(false, nd); if( !nd->u.scr.shop || !nd->u.scr.shop->items ) return false; @@ -1659,6 +1704,9 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; + nullpo_retv(nd); + nullpo_retv(sd); + npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */ switch( nd->u.scr.shop->type ) { @@ -1696,6 +1744,8 @@ bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; + nullpo_retr(false, nd); + nullpo_retr(false, sd); npc->trader_ok = false;/* clear */ snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname); @@ -1718,6 +1768,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po int i, price, w; unsigned short shop_size = 0; + nullpo_retr(ERROR_TYPE_SYSTEM, sd); if( amount <= 0 ) return ERROR_TYPE_ITEM_ID; @@ -2057,6 +2108,10 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st int key_identify = 0; int key_card[MAX_SLOTS]; + nullpo_ret(sd); + nullpo_ret(item_list); + nullpo_ret(nd); + // discard old contents script->cleararray_pc(sd, "@sold_nameid", (void*)0); script->cleararray_pc(sd, "@sold_quantity", (void*)0); @@ -2255,6 +2310,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args) { int src_id; + nullpo_ret(nd); src_id = va_arg(args, int); if (nd->src_id == src_id) npc->unload(nd, true); @@ -2263,6 +2319,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args) //Removes all npcs that are duplicates of the passed one. [Skotlex] void npc_unload_duplicates(struct npc_data* nd) { + nullpo_retv(nd); map->foreachnpc(npc->unload_dup_sub,nd->bl.id); } @@ -2386,6 +2443,7 @@ void npc_addsrcfile(const char* name) struct npc_src_list* file; struct npc_src_list* file_prev = NULL; + nullpo_retv(name); if( strcmpi(name, "clear") == 0 ) { npc->clearsrcfile(); @@ -2417,6 +2475,7 @@ void npc_delsrcfile(const char* name) struct npc_src_list* file = npc->src_files; struct npc_src_list* file_prev = NULL; + nullpo_retv(name); if( strcmpi(name, "all") == 0 ) { npc->clearsrcfile(); @@ -2504,6 +2563,8 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con struct npc_data* dnd;// duplicate npc char newname[NAME_LENGTH]; + nullpo_retv(nd); + nullpo_retv(name); // parse name p = strstr(name,"::"); if( p ) { // <Display name>::<Unique name> @@ -2559,6 +2620,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c int val = FAKE_NPC, i = 0; char viewid[1024]; // Max size of name from constants.conf, see script->read_constdb. + nullpo_retr(FAKE_NPC, w4); // Extract view ID / constant while (w4[i] != '\0') { if (ISSPACE(w4[i]) || w4[i] == '/' || w4[i] == ',') @@ -2590,6 +2652,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c // Checks if given view is an ID or constant. bool npc_viewisid(const char * viewid) { + nullpo_retr(false, viewid); if (atoi(viewid) != FAKE_NPC) { // Loop through view, looking for non-numeric character. while (*viewid) { @@ -2636,6 +2699,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short int i, flag = 0; struct npc_data *nd; + nullpo_retr(NULL, name); + nd = npc->create_npc(WARP, from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); @@ -2684,6 +2749,9 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const char mapname[32], to_mapname[32]; struct npc_data *nd; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w4); + // w1=<from map name>,<fromX>,<fromY>,<facing> // w4=<spanx>,<spany>,<to map name>,<toX>,<toY> if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3 @@ -2755,6 +2823,8 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const struct npc_data *nd; enum npc_subtype type; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w4); if( strcmp(w1,"-") == 0 ) { // 'floating' shop x = y = dir = 0; @@ -2869,6 +2939,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) { int i; + nullpo_retv(label_list); for( i = 0; i < script->label_count; i++ ) { const char* lname = script->get_str(script->labels[i].key); int lpos = script->labels[i].pos; @@ -2995,6 +3066,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con int label_list_num; struct npc_data* nd; + nullpo_retr(NULL, w1); if (strcmp(w1, "-") == 0) { // floating npc x = 0; @@ -3131,6 +3203,9 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i int i; bool retval = true; + nullpo_retr(false, nd); + nullpo_retr(false, snd); + ++npc_script; nd->u.scr.xs = xs; nd->u.scr.ys = ys; @@ -3175,6 +3250,9 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i */ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { + nullpo_retr(false, nd); + nullpo_retr(false, snd); + ++npc_shop; nd->u.shop.shop_item = snd->u.shop.shop_item; nd->u.shop.count = snd->u.shop.count; @@ -3190,6 +3268,9 @@ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int */ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { + nullpo_retr(false, nd); + nullpo_retr(false, snd); + ++npc_warp; nd->u.warp.xs = xs; nd->u.warp.ys = ys; @@ -3219,6 +3300,9 @@ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int */ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { + nullpo_retr(false, nd); + nullpo_retr(false, snd); + nd->src_id = snd->bl.id; switch (nd->subtype) { case SCRIPT: @@ -3284,6 +3368,8 @@ const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3, struct npc_data* dnd; end = strchr(start,'\n'); + nullpo_retr(end, w2); + nullpo_retr(end, w4); length = strlen(w2); // get the npc being duplicated @@ -3368,7 +3454,13 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) int dm = -1, im = -1, xs = -1, ys = -1; struct npc_data *nd = NULL; - if( m == -1 || map->list[m].instance_id == -1 ) + if (m == -1) + return 1; + + Assert_retr(1, m >= 0 && m < map->count); + nullpo_retr(1, snd); + + if (map->list[m].instance_id == -1) return 1; snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map->list[m].instance_id, snd->bl.id); @@ -3412,10 +3504,15 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) } //Set mapcell CELL_NPC to trigger event later -void npc_setcells(struct npc_data* nd) { - int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; +void npc_setcells(struct npc_data* nd) +{ + int16 m, x, y, xs, ys; int i,j; + nullpo_retv(nd); + m = nd->bl.m; + x = nd->bl.x; + y = nd->bl.y; switch(nd->subtype) { case WARP: xs = nd->u.warp.xs; @@ -3457,9 +3554,13 @@ int npc_unsetcells_sub(struct block_list *bl, va_list ap) } void npc_unsetcells(struct npc_data* nd) { - int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; + int16 m, x, y, xs, ys; int i,j, x0, x1, y0, y1; + nullpo_retv(nd); + m = nd->bl.m; + x = nd->bl.x; + y = nd->bl.y; switch(nd->subtype) { case WARP: xs = nd->u.warp.xs; @@ -3494,7 +3595,9 @@ void npc_unsetcells(struct npc_data* nd) { void npc_movenpc(struct npc_data* nd, int16 x, int16 y) { - const int16 m = nd->bl.m; + int16 m; + nullpo_retv(nd); + m = nd->bl.m; if (m < 0 || nd->bl.prev == NULL) return; //Not on a map. x = cap_value(x, 0, map->list[m].xs-1); @@ -3512,6 +3615,7 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y) void npc_setdisplayname(struct npc_data* nd, const char* newname) { nullpo_retv(nd); + nullpo_retv(newname); safestrncpy(nd->name, newname, sizeof(nd->name)); if( map->list[nd->bl.m].users ) @@ -3546,6 +3650,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c size_t len; nullpo_ret(sd); + nullpo_ret(message); if( ev == NULL || (nd = ev->nd) == NULL ) { ShowError("npc_event: event not found [%s]\n", eventname); @@ -3631,6 +3736,13 @@ const char *npc_parse_function(const char *w1, const char *w2, const char *w3, c const char* end; const char* script_start; + nullpo_retr(NULL, w1); + nullpo_retr(NULL, w2); + nullpo_retr(NULL, w3); + nullpo_retr(NULL, w4); + nullpo_retr(NULL, start); + nullpo_retr(NULL, retval); + script_start = strstr(start,"\t{"); end = strchr(start,'\n'); if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) { @@ -3674,6 +3786,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn) { int i; + nullpo_retv(mobspawn); for( i = mobspawn->active; i < mobspawn->num; ++i ) { struct mob_data* md = mob->spawn_dataset(mobspawn); md->spawn = mobspawn; @@ -3707,6 +3820,11 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const struct spawn_data mobspawn, *data; struct mob_db* db; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w2); + nullpo_retr(strchr(start,'\n'), w3); + nullpo_retr(strchr(start,'\n'), w4); + memset(&mobspawn, 0, sizeof(struct spawn_data)); mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0); @@ -3913,6 +4031,9 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co char mapname[32]; int state = 1; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w3); + // w1=<mapname> if( sscanf(w1, "%31[^,]", mapname) != 1 ) { @@ -4337,6 +4458,7 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co */ const char *npc_parse_unknown_object(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval) { + nullpo_retr(start, retval); ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); start = strchr(start,'\n');// skip and continue *retval = EXIT_FAILURE; @@ -4361,6 +4483,8 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { char* buffer; const char* p; + nullpo_retr(EXIT_FAILURE, filepath); + // read whole file to buffer fp = fopen(filepath, "rb"); if( fp == NULL ) { @@ -4618,6 +4742,7 @@ void npc_read_event_script(void) int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args) { struct npc_path_data *npd = DB->data2ptr(data); + nullpo_ret(npd); if (npd->path) aFree(npd->path); return 0; @@ -4761,6 +4886,8 @@ bool npc_unloadfile(const char *filepath) struct npc_data* nd = NULL; bool found = false; + nullpo_retr(false, filepath); + for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) { if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems found = true; @@ -4799,6 +4926,9 @@ int do_final_npc(void) { void npc_debug_warps_sub(struct npc_data* nd) { int16 m; + + nullpo_retv(nd); + if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0) return; |