Bug Summary

File:difs/resource.c
Location:line 327, column 13
Description:Dereference of undefined pointer value

Annotated Source Code

1/*
2Copyright 1987, 1998 The Open Group
3
4Permission to use, copy, modify, distribute, and sell this software and its
5documentation for any purpose is hereby granted without fee, provided that
6the above copyright notice appear in all copies and that both that
7copyright notice and this permission notice appear in supporting
8documentation.
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of The Open Group shall not be
21used in advertising or otherwise to promote the sale, use or other dealings
22in this Software without prior written authorization from The Open Group.
23 * Copyright 1990, 1991 Network Computing Devices;
24 * Portions Copyright 1987 by Digital Equipment Corporation
25 *
26 * Permission to use, copy, modify, distribute, and sell this software and its
27 * documentation for any purpose is hereby granted without fee, provided that
28 * the above copyright notice appear in all copies and that both that
29 * copyright notice and this permission notice appear in supporting
30 * documentation, and that the names of Network Computing Devices,
31 * or Digital not be used in advertising or
32 * publicity pertaining to distribution of the software without specific,
33 * written prior permission. Network Computing Devices, or Digital
34 * make no representations about the
35 * suitability of this software for any purpose. It is provided "as is"
36 * without express or implied warranty.
37 *
38 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
39 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
40 * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE
41 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
42 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
43 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
44 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
45 *
46 * %W% %G%
47 *
48 */
49/*
50 * a resource is a 32 bit quantity. the upper 12 bits are client id.
51 * client provides a 19 bit resource id. this is "hashed" by me by
52 * taking the 10 lower bits and xor'ing with the mid 10 bits.
53 *
54 * It is sometimes necessary for the server to create an ID that looks
55 * like it belongs to a client. This ID, however, must not be one
56 * the client actually can create, or we have the potential for conflict.
57 * The 20th bit of the ID is resevered for the server's use for this
58 * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
59 * 1, and an otherwise unused ID in the low 19 bits, we can create a
60 * resource "owned" by the client.
61 *
62 * The following IDs are currently reserved for siccing on the client:
63 * 1 - allocated color to be freed when the client dies
64 */
65
66#include "config.h"
67
68#include <X11/fonts/FS.h>
69#include "misc.h"
70#include "os.h"
71#include "fsresource.h"
72#include "clientstr.h"
73#include "dispatch.h"
74#include "globals.h"
75#include "difs.h"
76
77static void rebuild_table(int client);
78
79#define INITBUCKETS64 64
80#define INITHASHSIZE6 6
81#define MAXHASHSIZE11 11
82
83typedef struct _Resource {
84 struct _Resource *next;
85 FSID id;
86 RESTYPE type;
87 pointer value;
88} ResourceRec, *ResourcePtr;
89
90#define NullResource((ResourcePtr)((void *)0)) ((ResourcePtr)NULL((void *)0))
91
92typedef struct _ClientResource {
93 ResourcePtr *resources;
94 int elements;
95 int buckets;
96 int hashsize; /* log(2)(buckets) */
97 FSID fakeID;
98 FSID endFakeID;
99 FSID expectID;
100} ClientResourceRec;
101
102static RESTYPE lastResourceType;
103static RESTYPE TypeMask;
104
105typedef int (*DeleteType) (void *, FSID);
106
107static DeleteType *DeleteFuncs = (DeleteType *) NULL((void *)0);
108
109
110static ClientResourceRec clientTable[MAXCLIENTS128];
111
112/*****************
113 * InitClientResources
114 * When a new client is created, call this to allocate space
115 * in resource table
116 *****************/
117
118int
119NoneDeleteFunc (void *ptr, FSID id)
120{
121 return FSSuccess-1;
122}
123
124Bool
125InitClientResources(ClientPtr client)
126{
127 register int i,
128 j;
129
130 if (client == serverClient) {
131 lastResourceType = RT_LASTPREDEF((RESTYPE)2);
132 TypeMask = RC_LASTPREDEF((RESTYPE)1<<31) - 1;
133 if (DeleteFuncs)
134 fsfree(DeleteFuncs)FSfree((pointer)DeleteFuncs);
135 DeleteFuncs = (DeleteType *) fsalloc((lastResourceType + 1) *FSalloc((unsigned long)(lastResourceType + 1) * sizeof(DeleteType
))
136 sizeof(DeleteType))FSalloc((unsigned long)(lastResourceType + 1) * sizeof(DeleteType
))
;
137 if (!DeleteFuncs)
138 return FALSE0;
139 DeleteFuncs[RT_NONE((RESTYPE)0) & TypeMask] = NoneDeleteFunc;
140 DeleteFuncs[RT_FONT((RESTYPE)1) & TypeMask] = (DeleteType)CloseClientFont;
141 DeleteFuncs[RT_AUTHCONT((RESTYPE)2) & TypeMask] = (DeleteType)DeleteAuthCont;
142 }
143 clientTable[i = client->index].resources =
144 (ResourcePtr *) fsalloc(INITBUCKETS * sizeof(ResourcePtr))FSalloc((unsigned long)64 * sizeof(ResourcePtr));
145 if (!clientTable[i].resources)
146 return FALSE0;
147 clientTable[i].buckets = INITBUCKETS64;
148 clientTable[i].elements = 0;
149 clientTable[i].hashsize = INITHASHSIZE6;
150 clientTable[i].fakeID = SERVER_BIT0x20000000;
151 clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK0x3FFFFF) + 1;
152 for (j = 0; j < INITBUCKETS64; j++) {
153 clientTable[i].resources[j] = NullResource((ResourcePtr)((void *)0));
154 }
155 return TRUE1;
156}
157
158static int
159hash(int client, FSID id)
160{
161 id &= RESOURCE_ID_MASK0x3FFFFF;
162 switch (clientTable[client].hashsize) {
163 case 6:
164 return ((int) (0x03F & (id ^ (id >> 6) ^ (id >> 12))));
165 case 7:
166 return ((int) (0x07F & (id ^ (id >> 7) ^ (id >> 13))));
167 case 8:
168 return ((int) (0x0FF & (id ^ (id >> 8) ^ (id >> 16))));
169 case 9:
170 return ((int) (0x1FF & (id ^ (id >> 9))));
171 case 10:
172 return ((int) (0x3FF & (id ^ (id >> 10))));
173 case 11:
174 return ((int) (0x7FF & (id ^ (id >> 11))));
175 }
176 return -1;
177}
178
179
180static Font
181AvailableID(
182 register int client,
183 register FSID id,
184 register FSID maxid,
185 register FSID goodid)
186{
187 register ResourcePtr res;
188
189 if ((goodid >= id) && (goodid <= maxid))
190 return goodid;
191 for (; id <= maxid; id++)
192 {
193 res = clientTable[client].resources[hash(client, id)];
194 while (res && (res->id != id))
195 res = res->next;
196 if (!res)
197 return id;
198 }
199 return 0;
200}
201
202/*
203 * Return the next usable fake client ID.
204 *
205 * Normally this is just the next one in line, but if we've used the last
206 * in the range, we need to find a new range of safe IDs to avoid
207 * over-running another client.
208 */
209
210FSID
211FakeClientID(int client)
212{
213 register FSID id, maxid;
214 register ResourcePtr *resp;
215 register ResourcePtr res;
216 register int i;
217 FSID goodid;
218
219 id = clientTable[client].fakeID++;
220 if (id != clientTable[client].endFakeID)
221 return id;
222 id = ((Mask)client << CLIENTOFFSET22) | SERVER_BIT0x20000000;
223 maxid = id | RESOURCE_ID_MASK0x3FFFFF;
224 goodid = 0;
225 for (resp = clientTable[client].resources, i = clientTable[client].buckets;
226 --i >= 0;)
227 {
228 for (res = *resp++; res; res = res->next)
229 {
230 if ((res->id < id) || (res->id > maxid))
231 continue;
232 if (((res->id - id) >= (maxid - res->id)) ?
233 (goodid = AvailableID(client, id, res->id - 1, goodid)) :
234 !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
235 maxid = res->id - 1;
236 else
237 id = res->id + 1;
238 }
239 }
240 if (id > maxid) {
241 if (!client)
242 FatalError("FakeClientID: server internal ids exhausted\n");
243 MarkClientException(clients[client]);
244 id = ((Mask)client << CLIENTOFFSET22) | (SERVER_BIT0x20000000 * 3);
245 maxid = id | RESOURCE_ID_MASK0x3FFFFF;
246 }
247 clientTable[client].fakeID = id + 1;
248 clientTable[client].endFakeID = maxid + 1;
249 return id;
250}
251
252Bool
253AddResource(
254 int cid,
255 FSID id,
256 RESTYPE type,
257 pointer value)
258{
259 register ClientResourceRec *rrec;
260 register ResourcePtr res,
261 *head;
262
263 rrec = &clientTable[cid];
264 if (!rrec->buckets) {
1
Taking false branch
265 ErrorF("AddResource(%lx, %lx, %p), client=%d \n",
266 id, type, value, cid);
267 FatalError("client not in use\n");
268 }
269 if ((rrec->elements >= 4 * rrec->buckets) &&
2
Taking true branch
270 (rrec->hashsize < MAXHASHSIZE11))
271 rebuild_table(cid);
3
Calling 'rebuild_table'
272 head = &rrec->resources[hash(cid, id)];
273 res = (ResourcePtr) fsalloc(sizeof(ResourceRec))FSalloc((unsigned long)sizeof(ResourceRec));
274 if (!res) {
275 (*DeleteFuncs[type & TypeMask]) (value, id);
276 return FALSE0;
277 }
278 res->next = *head;
279 res->id = id;
280 res->type = type;
281 res->value = value;
282 *head = res;
283 rrec->elements++;
284 if (!(id & SERVER_BIT0x20000000) && (id >= rrec->expectID))
285 rrec->expectID = id + 1;
286 return TRUE1;
287}
288
289static void
290rebuild_table(int client)
291{
292 register int j;
293 register ResourcePtr res,
294 next;
295 ResourcePtr **tails,
296 *resources;
297 register ResourcePtr **tptr,
298 *rptr;
299
300 /*
301 * For now, preserve insertion order, since some ddx layers depend on
302 * resources being free in the opposite order they are added.
303 */
304
305 j = 2 * clientTable[client].buckets;
306 tails = (ResourcePtr **) ALLOCATE_LOCAL(j * sizeof(ResourcePtr *))__builtin_alloca((int)(j * sizeof(ResourcePtr *)));
307 if (!tails)
4
Taking false branch
308 return;
309 resources = (ResourcePtr *) fsalloc(j * sizeof(ResourcePtr))FSalloc((unsigned long)j * sizeof(ResourcePtr));
310 if (!resources) {
5
Assuming 'resources' is non-null
6
Taking false branch
311 DEALLOCATE_LOCAL(tails)do {} while(0);
312 return;
313 }
314 for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) {
7
Loop condition is false. Execution continues on line 318
315 *rptr = NullResource((ResourcePtr)((void *)0));
316 *tptr = rptr;
317 }
318 clientTable[client].hashsize++;
319 for (j = clientTable[client].buckets,
8
Loop condition is true. Entering loop body
320 rptr = clientTable[client].resources;
321 --j >= 0;
322 rptr++) {
323 for (res = *rptr; res; res = next) {
9
Loop condition is true. Entering loop body
324 next = res->next;
325 res->next = NullResource((ResourcePtr)((void *)0));
326 tptr = &tails[hash(client, res->id)];
327 **tptr = res;
10
Dereference of undefined pointer value
328 *tptr = &res->next;
329 }
330 }
331 DEALLOCATE_LOCAL(tails)do {} while(0);
332 clientTable[client].buckets *= 2;
333 fsfree(clientTable[client].resources)FSfree((pointer)clientTable[client].resources);
334 clientTable[client].resources = resources;
335}
336
337void
338FreeResource(
339 int cid,
340 FSID id,
341 RESTYPE skipDeleteFuncType)
342{
343 register ResourcePtr res;
344 register ResourcePtr *prev,
345 *head;
346 register int *eltptr;
347 int elements;
348 Bool gotOne = FALSE0;
349
350 if (clientTable[cid].buckets) {
351 head = &clientTable[cid].resources[hash(cid, id)];
352 eltptr = &clientTable[cid].elements;
353
354 prev = head;
355 while ((res = *prev) != (ResourcePtr) 0) {
356 if (res->id == id) {
357 RESTYPE rtype = res->type;
358
359 *prev = res->next;
360 elements = --*eltptr;
361 if (rtype != skipDeleteFuncType)
362 (*DeleteFuncs[rtype & TypeMask]) (res->value, res->id);
363 fsfree(res)FSfree((pointer)res);
364 if (*eltptr != elements)
365 prev = head;/* prev may no longer be valid */
366 gotOne = TRUE1;
367 } else
368 prev = &res->next;
369 }
370 }
371 if (!gotOne)
372 FatalError("freeing resource id=%lX which isn't there\n", id);
373}
374
375
376void
377FreeClientResources(ClientPtr client)
378{
379 register ResourcePtr *resources;
380 register ResourcePtr this;
381 int j;
382
383 /*
384 * This routine shouldn't be called with a null client, but just in case
385 * ...
386 */
387
388 if (!client)
389 return;
390
391 resources = clientTable[client->index].resources;
392 for (j = 0; j < clientTable[client->index].buckets; j++) {
393 /*
394 * It may seem silly to update the head of this resource list as we
395 * delete the members, since the entire list will be deleted any way,
396 * but there are some resource deletion functions "FreeClientPixels"
397 * for one which do a LookupID on another resource id (a Colormap id
398 * in this case), so the resource list must be kept valid up to the
399 * point that it is deleted, so every time we delete a resource, we
400 * must update the head, just like in free_resource. I hope that this
401 * doesn't slow down mass deletion appreciably. PRH
402 */
403
404 ResourcePtr *head;
405
406 head = &resources[j];
407
408 for (this = *head; this; this = *head) {
409 RESTYPE rtype = this->type;
410
411 *head = this->next;
412 (*DeleteFuncs[rtype & TypeMask]) (this->value, this->id);
413 fsfree(this)FSfree((pointer)this);
414 }
415 }
416 fsfree(clientTable[client->index].resources)FSfree((pointer)clientTable[client->index].resources);
417 clientTable[client->index].buckets = 0;
418}
419
420void
421FreeAllResources(void)
422{
423 int i;
424
425 for (i = 0; i < currentMaxClients; i++) {
426 if (clientTable[i].buckets)
427 FreeClientResources(clients[i]);
428 }
429}
430
431/*
432 * lookup_id_by_type returns the object with the given id and type, else NULL.
433 */
434pointer
435LookupIDByType(
436 int cid,
437 FSID id,
438 RESTYPE rtype)
439{
440 register ResourcePtr res;
441
442 if (clientTable[cid].buckets) {
443 res = clientTable[cid].resources[hash(cid, id)];
444
445 for (; res; res = res->next)
446 if ((res->id == id) && (res->type == rtype))
447 return res->value;
448 }
449 return (pointer) NULL((void *)0);
450}
451