summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2016-04-05 13:15:04 +0200
committerHaru <haru@dotalux.com>2016-04-05 13:15:04 +0200
commit187c0b6b288a6a4267aeb949e054dd8fabde6627 (patch)
treec3bbb6a5999659f2da840563fa6f46a517677145
parent73a617651b290eef4d5c1e6900eed6cb3526c307 (diff)
parentc3eb11ff4c048a5ff6770dc57659ed7798576a97 (diff)
downloadhercules-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.c114
-rw-r--r--src/map/mapreg_sql.c7
-rw-r--r--src/map/mercenary.c17
-rw-r--r--src/map/mob.c95
-rw-r--r--src/map/npc.c156
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;