Bug Summary

File:server/sv_init.cpp
Location:line 47, column 45
Description:Access to field 'mAsm' results in a dereference of a null pointer (loaded from variable 'map')

Annotated Source Code

1/**
2 * @file
3 * @brief Server initialisation stuff.
4 */
5
6/*
7All original material Copyright (C) 2002-2011 UFO: Alien Invasion.
8
9Original file from Quake 2 v3.21: quake2-2.31/server/sv_init.c
10
11Copyright (C) 1997-2001 Id Software, Inc.
12
13This program is free software; you can redistribute it and/or
14modify it under the terms of the GNU General Public License
15as published by the Free Software Foundation; either version 2
16of the License, or (at your option) any later version.
17
18This program is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21
22See the GNU General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; if not, write to the Free Software
26Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28*/
29
30#include "server.h"
31#include "sv_rma.h"
32#include "../shared/parse.h"
33
34serverInstanceStatic_t svs; /* persistant server info */
35serverInstanceGame_t * sv; /* local server */
36
37/**
38 * @brief Get the map title for a given map
39 * @note the title string must be translated client side
40 * @return Never NULL - mapname or maptitle (if defined in assembly)
41 */
42static const char* SV_GetMapTitle (const mapInfo_t *map, const char* const mapname)
43{
44 assert(mapname)(__builtin_expect(!(mapname), 0) ? __assert_rtn(__func__, "src/server/sv_init.cpp"
, 44, "mapname") : (void)0)
;
45
46 if (mapname[0] == '+') {
6
Taking true branch
47 const mAssembly_t *mAsm = &map->mAssembly[map->mAsm];
7
Access to field 'mAsm' results in a dereference of a null pointer (loaded from variable 'map')
48 if (mAsm && mAsm->title[0]) {
49 /* return the assembly title itself - must be translated client side */
50 if (mAsm->title[0] == '_')
51 return mAsm->title + 1;
52 else {
53 Com_Printf("The assembly title '%s' is not marked as translatable\n", mAsm->title);
54 return mAsm->title;
55 }
56 }
57 }
58 return mapname;
59}
60
61/**
62 * @sa CL_ServerListDiscoveryCallback
63 */
64static void SV_DiscoveryCallback (struct datagram_socket *s, const char *buf, int len, struct sockaddr *from)
65{
66 const char match[] = "discover";
67 if (len == sizeof(match) && memcmp(buf, match, len) == 0) {
68 const char msg[] = "discovered";
69 NET_DatagramSend(s, msg, sizeof(msg), from);
70 }
71}
72
73/**
74 * @brief A brand new game has been started
75 */
76static void SV_InitGame (void)
77{
78 /* allow next change after map change or restart */
79 sv_maxclients->flags |= CVAR_LATCH16;
80
81 /* get any latched variable changes (sv_maxclients, etc) */
82 Cvar_UpdateLatchedVars();
83
84 if (svs.serverMutex)
85 Sys_Error("There is still a server running");
86
87 svs.clients = Mem_PoolAllocTypeN(client_t, sv_maxclients->integer, sv_genericPool)static_cast<client_t*>(_Mem_Alloc((sizeof(client_t) * (
sv_maxclients->integer)),true,((sv_genericPool)),(0),"src/server/sv_init.cpp"
,87))
;
88 svs.serverMutex = TH_MutexCreate("server");
89
90 /* init network stuff */
91 if (sv_maxclients->integer > 1) {
92 svs.initialized = SV_Start(NULL__null, port->string, &SV_ReadPacket);
93 svs.netDatagramSocket = NET_DatagramSocketNew(NULL__null, port->string, &SV_DiscoveryCallback);
94 } else
95 svs.initialized = SV_Start(NULL__null, NULL__null, &SV_ReadPacket);
96
97 SV_Heartbeat_f();
98
99 /* init game */
100 SV_InitGameProgs();
101
102 if (sv_maxclients->integer != 1 && (sv_dedicated->integer || sv_public->integer))
103 SV_SetMaster_f();
104}
105
106/**
107 * @brief Change the server to a new map, taking all connected clients along with it.
108 * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode
109 * @sa SV_AssembleMap
110 * @sa CM_LoadMap
111 * @sa Com_SetServerState
112 */
113void SV_Map (bool day, const char *levelstring, const char *assembly)
114{
115 int i;
116 unsigned checksum = 0;
117 char * map = SV_GetConfigString(CS_TILES16);
118 char * pos = SV_GetConfigString(CS_POSITIONS(16 +25));
119 mapInfo_t *randomMap = NULL__null;
120 client_t *cl;
121
122 /* any partially connected client will be restarted */
123 Com_SetServerState(ss_restart);
124
125 /* the game is just starting */
126 SV_InitGame();
127
128 if (!svs.initialized) {
1
Taking false branch
129 Com_Printf("Could not spawn the server\n");
130 return;
131 }
132
133 assert(levelstring[0] != '\0')(__builtin_expect(!(levelstring[0] != '\0'), 0) ? __assert_rtn
(__func__, "src/server/sv_init.cpp", 133, "levelstring[0] != '\\0'"
) : (void)0)
;
134
135 Com_DPrintf(DEBUG_SERVER0x40, "SpawnServer: %s\n", levelstring);
136
137 /* save name for levels that don't set message */
138 SV_SetConfigString(CS_NAME, levelstring)SV_SetConfigString(0, levelstring);
139 SV_SetConfigString(CS_LIGHTMAP, day)SV_SetConfigString(12, day);
140
141 Q_strncpyz(sv->name, levelstring, sizeof(sv->name))Q_strncpyzDebug( sv->name, levelstring, sizeof(sv->name
), "src/server/sv_init.cpp", 141 )
;
142
143 /* set serverinfo variable */
144 sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO4 | CVAR_NOSET8);
145
146 /* notify the client in case of a listening server */
147 SCR_BeginLoadingPlaque();
148
149 if (assembly)
2
Taking true branch
150 Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly))Q_strncpyzDebug( sv->assembly, assembly, sizeof(sv->assembly
), "src/server/sv_init.cpp", 150 )
;
151 else
152 sv->assembly[0] = '\0';
153
154 /* leave slots at start for clients only */
155 cl = NULL__null;
156 while ((cl = SV_GetNextClient(cl)) != NULL__null) {
3
Loop condition is false. Execution continues on line 163
157 /* needs to reconnect */
158 if (cl->state >= cs_spawning)
159 SV_SetClientState(cl, cs_connected);
160 }
161
162 /* assemble and load the map */
163 if (levelstring[0] == '+') {
4
Taking false branch
164 randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, 0);
165 if (!randomMap) {
166 Com_Printf("Could not load assembly for map '%s'\n", levelstring);
167 return;
168 }
169 } else {
170 SV_SetConfigString(CS_TILES, levelstring)SV_SetConfigString(16, levelstring);
171 SV_SetConfigString(CS_POSITIONS, assembly ? assembly : "")SV_SetConfigString((16 +25), assembly ? assembly : "");
172 }
173
174 CM_LoadMap(map, day, pos, &sv->mapData, &sv->mapTiles);
175
176 Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum);
177 SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum)SV_SetConfigString(3, sv->mapData.mapChecksum);
178
179 checksum = Com_GetScriptChecksum();
180
181 Com_Printf("ufo script checksum %u\n", checksum);
182 SV_SetConfigString(CS_UFOCHECKSUM, checksum)SV_SetConfigString(10, checksum);
183 SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs)SV_SetConfigString(11, csi.numODs);
184 SV_SetConfigString(CS_VERSION, UFO_VERSION)SV_SetConfigString(9, "2.5-dev");
185 SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring))SV_SetConfigString(1, SV_GetMapTitle(randomMap, levelstring));
5
Within the expansion of the macro 'SV_SetConfigString':
a
Calling 'SV_GetMapTitle'
186 if (Q_strstart(SV_GetConfigString(CS_MAPTITLE1), "b/")) {
187 /* For base attack, CS_MAPTITLE contains too many chars */
188 SV_SetConfigString(CS_MAPTITLE, "Base attack")SV_SetConfigString(1, "Base attack");
189 SV_SetConfigString(CS_NAME, ".baseattack")SV_SetConfigString(0, ".baseattack");
190 }
191
192 /* clear random-map assembly data */
193 Mem_Free(randomMap)_Mem_Free((randomMap),"src/server/sv_init.cpp",193);
194 randomMap = NULL__null;
195
196 /* clear physics interaction links */
197 SV_ClearWorld();
198
199 /* fix this! */
200 for (i = 1; i <= sv->mapData.numInline; i++)
201 sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i));
202
203 /* precache and static commands can be issued during map initialization */
204 Com_SetServerState(ss_loading);
205
206 TH_MutexLock(svs.serverMutex)_TH_MutexLock((svs.serverMutex), "src/server/sv_init.cpp", 206
)
;
207 /* load and spawn all other entities */
208 svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP12), sv->mapData.mapEntityString);
209 TH_MutexUnlock(svs.serverMutex)_TH_MutexUnlock((svs.serverMutex), "src/server/sv_init.cpp", 209
)
;
210
211 /* all precaches are complete */
212 Com_SetServerState(ss_game);
213
214 Com_Printf("-------------------------------------\n");
215
216 Cbuf_CopyToDefer();
217}