File: | record/set.c |
Location: | line 357, column 5 |
Description: | Null pointer argument in call to memory copy function |
1 | /* | |||||
2 | ||||||
3 | Copyright 1995, 1998 The Open Group | |||||
4 | ||||||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |||||
6 | documentation for any purpose is hereby granted without fee, provided that | |||||
7 | the above copyright notice appear in all copies and that both that | |||||
8 | copyright notice and this permission notice appear in supporting | |||||
9 | documentation. | |||||
10 | ||||||
11 | The above copyright notice and this permission notice shall be | |||||
12 | included in all copies or substantial portions of the Software. | |||||
13 | ||||||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||||
17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||||
18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||||
19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||||
20 | OTHER DEALINGS IN THE SOFTWARE. | |||||
21 | ||||||
22 | Except as contained in this notice, the name of The Open Group shall | |||||
23 | not be used in advertising or otherwise to promote the sale, use or | |||||
24 | other dealings in this Software without prior written authorization | |||||
25 | from The Open Group. | |||||
26 | ||||||
27 | */ | |||||
28 | ||||||
29 | /* | |||||
30 | ||||||
31 | See the header set.h for a description of the set ADT. | |||||
32 | ||||||
33 | Implementation Strategy | |||||
34 | ||||||
35 | A bit vector is an obvious choice to represent the set, but may take | |||||
36 | too much memory, depending on the numerically largest member in the | |||||
37 | set. One expected common case is for the client to ask for *all* | |||||
38 | protocol. This means it would ask for minor opcodes 0 through 65535. | |||||
39 | Representing this as a bit vector takes 8K -- and there may be | |||||
40 | multiple minor opcode intervals, as many as one per major (extension) | |||||
41 | opcode). In such cases, a list-of-intervals representation would be | |||||
42 | preferable to reduce memory consumption. Both representations will be | |||||
43 | implemented, and RecordCreateSet will decide heuristically which one | |||||
44 | to use based on the set members. | |||||
45 | ||||||
46 | */ | |||||
47 | ||||||
48 | #ifdef HAVE_DIX_CONFIG_H1 | |||||
49 | #include <dix-config.h> | |||||
50 | #endif | |||||
51 | ||||||
52 | #include <string.h> | |||||
53 | ||||||
54 | #include "misc.h" | |||||
55 | #include "set.h" | |||||
56 | ||||||
57 | static int | |||||
58 | maxMemberInInterval(RecordSetInterval * pIntervals, int nIntervals) | |||||
59 | { | |||||
60 | int i; | |||||
61 | int maxMember = -1; | |||||
62 | ||||||
63 | for (i = 0; i < nIntervals; i++) { | |||||
64 | if (maxMember < (int) pIntervals[i].last) | |||||
65 | maxMember = pIntervals[i].last; | |||||
66 | } | |||||
67 | return maxMember; | |||||
68 | } | |||||
69 | ||||||
70 | static void | |||||
71 | NoopDestroySet(RecordSetPtr pSet) | |||||
72 | { | |||||
73 | } | |||||
74 | ||||||
75 | /***************************************************************************/ | |||||
76 | ||||||
77 | /* set operations for bit vector representation */ | |||||
78 | ||||||
79 | typedef struct { | |||||
80 | RecordSetRec baseSet; | |||||
81 | int maxMember; | |||||
82 | /* followed by the bit vector itself */ | |||||
83 | } BitVectorSet, *BitVectorSetPtr; | |||||
84 | ||||||
85 | #define BITS_PER_LONG(sizeof(unsigned long) * 8) (sizeof(unsigned long) * 8) | |||||
86 | ||||||
87 | static void | |||||
88 | BitVectorDestroySet(RecordSetPtr pSet) | |||||
89 | { | |||||
90 | free(pSet); | |||||
91 | } | |||||
92 | ||||||
93 | static unsigned long | |||||
94 | BitVectorIsMemberOfSet(RecordSetPtr pSet, int pm) | |||||
95 | { | |||||
96 | BitVectorSetPtr pbvs = (BitVectorSetPtr) pSet; | |||||
97 | unsigned long *pbitvec; | |||||
98 | ||||||
99 | if ((int) pm > pbvs->maxMember) | |||||
100 | return FALSE0; | |||||
101 | pbitvec = (unsigned long *) (&pbvs[1]); | |||||
102 | return (pbitvec[pm / BITS_PER_LONG(sizeof(unsigned long) * 8)] & | |||||
103 | ((unsigned long) 1 << (pm % BITS_PER_LONG(sizeof(unsigned long) * 8)))); | |||||
104 | } | |||||
105 | ||||||
106 | static int | |||||
107 | BitVectorFindBit(RecordSetPtr pSet, int iterbit, Bool bitval) | |||||
108 | { | |||||
109 | BitVectorSetPtr pbvs = (BitVectorSetPtr) pSet; | |||||
110 | unsigned long *pbitvec = (unsigned long *) (&pbvs[1]); | |||||
111 | int startlong; | |||||
112 | int startbit; | |||||
113 | int walkbit; | |||||
114 | int maxMember; | |||||
115 | unsigned long skipval; | |||||
116 | unsigned long bits; | |||||
117 | unsigned long usefulbits; | |||||
118 | ||||||
119 | startlong = iterbit / BITS_PER_LONG(sizeof(unsigned long) * 8); | |||||
120 | pbitvec += startlong; | |||||
121 | startbit = startlong * BITS_PER_LONG(sizeof(unsigned long) * 8); | |||||
122 | skipval = bitval ? 0L : ~0L; | |||||
123 | maxMember = pbvs->maxMember; | |||||
124 | ||||||
125 | if (startbit > maxMember) | |||||
126 | return -1; | |||||
127 | bits = *pbitvec; | |||||
128 | usefulbits = ~(((unsigned long) 1 << (iterbit - startbit)) - 1); | |||||
129 | if ((bits & usefulbits) == (skipval & usefulbits)) { | |||||
130 | pbitvec++; | |||||
131 | startbit += BITS_PER_LONG(sizeof(unsigned long) * 8); | |||||
132 | ||||||
133 | while (startbit <= maxMember && *pbitvec == skipval) { | |||||
134 | pbitvec++; | |||||
135 | startbit += BITS_PER_LONG(sizeof(unsigned long) * 8); | |||||
136 | } | |||||
137 | if (startbit > maxMember) | |||||
138 | return -1; | |||||
139 | } | |||||
140 | ||||||
141 | walkbit = (startbit < iterbit) ? iterbit - startbit : 0; | |||||
142 | ||||||
143 | bits = *pbitvec; | |||||
144 | while (walkbit < BITS_PER_LONG(sizeof(unsigned long) * 8) && | |||||
145 | ((!(bits & ((unsigned long) 1 << walkbit))) == bitval)) | |||||
146 | walkbit++; | |||||
147 | ||||||
148 | return startbit + walkbit; | |||||
149 | } | |||||
150 | ||||||
151 | static RecordSetIteratePtr | |||||
152 | BitVectorIterateSet(RecordSetPtr pSet, RecordSetIteratePtr pIter, | |||||
153 | RecordSetInterval * pInterval) | |||||
154 | { | |||||
155 | int iterbit = (int) (long) pIter; | |||||
156 | int b; | |||||
157 | ||||||
158 | b = BitVectorFindBit(pSet, iterbit, TRUE1); | |||||
159 | if (b == -1) | |||||
160 | return (RecordSetIteratePtr) 0; | |||||
161 | pInterval->first = b; | |||||
162 | ||||||
163 | b = BitVectorFindBit(pSet, b, FALSE0); | |||||
164 | pInterval->last = (b < 0) ? ((BitVectorSetPtr) pSet)->maxMember : b - 1; | |||||
165 | return (RecordSetIteratePtr) (long) (pInterval->last + 1); | |||||
166 | } | |||||
167 | ||||||
168 | static RecordSetOperations BitVectorSetOperations = { | |||||
169 | BitVectorDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet | |||||
170 | }; | |||||
171 | ||||||
172 | static RecordSetOperations BitVectorNoFreeOperations = { | |||||
173 | NoopDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet | |||||
174 | }; | |||||
175 | ||||||
176 | static int | |||||
177 | BitVectorSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals, | |||||
178 | int maxMember, int *alignment) | |||||
179 | { | |||||
180 | int nlongs; | |||||
181 | ||||||
182 | *alignment = sizeof(unsigned long); | |||||
183 | nlongs = (maxMember + BITS_PER_LONG(sizeof(unsigned long) * 8)) / BITS_PER_LONG(sizeof(unsigned long) * 8); | |||||
184 | return (sizeof(BitVectorSet) + nlongs * sizeof(unsigned long)); | |||||
185 | } | |||||
186 | ||||||
187 | static RecordSetPtr | |||||
188 | BitVectorCreateSet(RecordSetInterval * pIntervals, int nIntervals, | |||||
189 | void *pMem, int memsize) | |||||
190 | { | |||||
191 | BitVectorSetPtr pbvs; | |||||
192 | int i, j; | |||||
193 | unsigned long *pbitvec; | |||||
194 | ||||||
195 | /* allocate all storage needed by this set in one chunk */ | |||||
196 | ||||||
197 | if (pMem) { | |||||
198 | memset(pMem, 0, memsize)__builtin___memset_chk (pMem, 0, memsize, __builtin_object_size (pMem, 0)); | |||||
199 | pbvs = (BitVectorSetPtr) pMem; | |||||
200 | pbvs->baseSet.ops = &BitVectorNoFreeOperations; | |||||
201 | } | |||||
202 | else { | |||||
203 | pbvs = (BitVectorSetPtr) calloc(1, memsize); | |||||
204 | if (!pbvs) | |||||
205 | return NULL((void*)0); | |||||
206 | pbvs->baseSet.ops = &BitVectorSetOperations; | |||||
207 | } | |||||
208 | ||||||
209 | pbvs->maxMember = maxMemberInInterval(pIntervals, nIntervals); | |||||
210 | ||||||
211 | /* fill in the set */ | |||||
212 | ||||||
213 | pbitvec = (unsigned long *) (&pbvs[1]); | |||||
214 | for (i = 0; i < nIntervals; i++) { | |||||
215 | for (j = pIntervals[i].first; j <= (int) pIntervals[i].last; j++) { | |||||
216 | pbitvec[j / BITS_PER_LONG(sizeof(unsigned long) * 8)] |= | |||||
217 | ((unsigned long) 1 << (j % BITS_PER_LONG(sizeof(unsigned long) * 8))); | |||||
218 | } | |||||
219 | } | |||||
220 | return (RecordSetPtr) pbvs; | |||||
221 | } | |||||
222 | ||||||
223 | /***************************************************************************/ | |||||
224 | ||||||
225 | /* set operations for interval list representation */ | |||||
226 | ||||||
227 | typedef struct { | |||||
228 | RecordSetRec baseSet; | |||||
229 | int nIntervals; | |||||
230 | /* followed by the intervals (RecordSetInterval) */ | |||||
231 | } IntervalListSet, *IntervalListSetPtr; | |||||
232 | ||||||
233 | static void | |||||
234 | IntervalListDestroySet(RecordSetPtr pSet) | |||||
235 | { | |||||
236 | free(pSet); | |||||
237 | } | |||||
238 | ||||||
239 | static unsigned long | |||||
240 | IntervalListIsMemberOfSet(RecordSetPtr pSet, int pm) | |||||
241 | { | |||||
242 | IntervalListSetPtr prls = (IntervalListSetPtr) pSet; | |||||
243 | RecordSetInterval *pInterval = (RecordSetInterval *) (&prls[1]); | |||||
244 | int hi, lo, probe; | |||||
245 | ||||||
246 | /* binary search */ | |||||
247 | lo = 0; | |||||
248 | hi = prls->nIntervals - 1; | |||||
249 | while (lo <= hi) { | |||||
250 | probe = (hi + lo) / 2; | |||||
251 | if (pm >= pInterval[probe].first && pm <= pInterval[probe].last) | |||||
252 | return 1; | |||||
253 | else if (pm < pInterval[probe].first) | |||||
254 | hi = probe - 1; | |||||
255 | else | |||||
256 | lo = probe + 1; | |||||
257 | } | |||||
258 | return 0; | |||||
259 | } | |||||
260 | ||||||
261 | static RecordSetIteratePtr | |||||
262 | IntervalListIterateSet(RecordSetPtr pSet, RecordSetIteratePtr pIter, | |||||
263 | RecordSetInterval * pIntervalReturn) | |||||
264 | { | |||||
265 | RecordSetInterval *pInterval = (RecordSetInterval *) pIter; | |||||
266 | IntervalListSetPtr prls = (IntervalListSetPtr) pSet; | |||||
267 | ||||||
268 | if (pInterval == NULL((void*)0)) { | |||||
269 | pInterval = (RecordSetInterval *) (&prls[1]); | |||||
270 | } | |||||
271 | ||||||
272 | if ((pInterval - (RecordSetInterval *) (&prls[1])) < prls->nIntervals) { | |||||
273 | *pIntervalReturn = *pInterval; | |||||
274 | return (RecordSetIteratePtr) (++pInterval); | |||||
275 | } | |||||
276 | else | |||||
277 | return (RecordSetIteratePtr) NULL((void*)0); | |||||
278 | } | |||||
279 | ||||||
280 | static RecordSetOperations IntervalListSetOperations = { | |||||
281 | IntervalListDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet | |||||
282 | }; | |||||
283 | ||||||
284 | static RecordSetOperations IntervalListNoFreeOperations = { | |||||
285 | NoopDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet | |||||
286 | }; | |||||
287 | ||||||
288 | static int | |||||
289 | IntervalListMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals, | |||||
290 | int maxMember, int *alignment) | |||||
291 | { | |||||
292 | *alignment = sizeof(unsigned long); | |||||
293 | return sizeof(IntervalListSet) + nIntervals * sizeof(RecordSetInterval); | |||||
294 | } | |||||
295 | ||||||
296 | static RecordSetPtr | |||||
297 | IntervalListCreateSet(RecordSetInterval * pIntervals, int nIntervals, | |||||
298 | void *pMem, int memsize) | |||||
299 | { | |||||
300 | IntervalListSetPtr prls; | |||||
301 | int i, j, k; | |||||
302 | RecordSetInterval *stackIntervals = NULL((void*)0); | |||||
| ||||||
303 | CARD16 first; | |||||
304 | ||||||
305 | if (nIntervals > 0) { | |||||
306 | stackIntervals = | |||||
307 | (RecordSetInterval *) malloc(sizeof(RecordSetInterval) * | |||||
308 | nIntervals); | |||||
309 | if (!stackIntervals) | |||||
310 | return NULL((void*)0); | |||||
311 | ||||||
312 | /* sort intervals, store in stackIntervals (insertion sort) */ | |||||
313 | ||||||
314 | for (i = 0; i < nIntervals; i++) { | |||||
315 | first = pIntervals[i].first; | |||||
316 | for (j = 0; j < i; j++) { | |||||
317 | if (first < stackIntervals[j].first) | |||||
318 | break; | |||||
319 | } | |||||
320 | for (k = i; k > j; k--) { | |||||
321 | stackIntervals[k] = stackIntervals[k - 1]; | |||||
322 | } | |||||
323 | stackIntervals[j] = pIntervals[i]; | |||||
324 | } | |||||
325 | ||||||
326 | /* merge abutting/overlapping intervals */ | |||||
327 | ||||||
328 | for (i = 0; i < nIntervals - 1;) { | |||||
329 | if ((stackIntervals[i].last + (unsigned int) 1) < | |||||
330 | stackIntervals[i + 1].first) { | |||||
331 | i++; /* disjoint intervals */ | |||||
332 | } | |||||
333 | else { | |||||
334 | stackIntervals[i].last = max(stackIntervals[i].last,(((stackIntervals[i].last) > (stackIntervals[i + 1].last)) ? (stackIntervals[i].last) : (stackIntervals[i + 1].last)) | |||||
335 | stackIntervals[i + 1].last)(((stackIntervals[i].last) > (stackIntervals[i + 1].last)) ? (stackIntervals[i].last) : (stackIntervals[i + 1].last)); | |||||
336 | nIntervals--; | |||||
337 | for (j = i + 1; j < nIntervals; j++) | |||||
338 | stackIntervals[j] = stackIntervals[j + 1]; | |||||
339 | } | |||||
340 | } | |||||
341 | } | |||||
342 | ||||||
343 | /* allocate and fill in set structure */ | |||||
344 | ||||||
345 | if (pMem) { | |||||
346 | prls = (IntervalListSetPtr) pMem; | |||||
347 | prls->baseSet.ops = &IntervalListNoFreeOperations; | |||||
348 | } | |||||
349 | else { | |||||
350 | prls = (IntervalListSetPtr) | |||||
351 | malloc(sizeof(IntervalListSet) + | |||||
352 | nIntervals * sizeof(RecordSetInterval)); | |||||
353 | if (!prls) | |||||
354 | goto bailout; | |||||
355 | prls->baseSet.ops = &IntervalListSetOperations; | |||||
356 | } | |||||
357 | memcpy(&prls[1], stackIntervals, nIntervals * sizeof(RecordSetInterval))__builtin___memcpy_chk (&prls[1], stackIntervals, nIntervals * sizeof(RecordSetInterval), __builtin_object_size (&prls [1], 0)); | |||||
| ||||||
358 | prls->nIntervals = nIntervals; | |||||
359 | bailout: | |||||
360 | free(stackIntervals); | |||||
361 | return (RecordSetPtr) prls; | |||||
362 | } | |||||
363 | ||||||
364 | typedef RecordSetPtr(*RecordCreateSetProcPtr) (RecordSetInterval * pIntervals, | |||||
365 | int nIntervals, | |||||
366 | void *pMem, int memsize); | |||||
367 | ||||||
368 | static int | |||||
369 | _RecordSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals, | |||||
370 | int *alignment, | |||||
371 | RecordCreateSetProcPtr * ppCreateSet) | |||||
372 | { | |||||
373 | int bmsize, rlsize, bma, rla; | |||||
374 | int maxMember; | |||||
375 | ||||||
376 | /* find maximum member of set so we know how big to make the bit vector */ | |||||
377 | maxMember = maxMemberInInterval(pIntervals, nIntervals); | |||||
378 | ||||||
379 | bmsize = BitVectorSetMemoryRequirements(pIntervals, nIntervals, maxMember, | |||||
380 | &bma); | |||||
381 | rlsize = IntervalListMemoryRequirements(pIntervals, nIntervals, maxMember, | |||||
382 | &rla); | |||||
383 | if (((nIntervals > 1) && (maxMember <= 255)) | |||||
384 | || (bmsize < rlsize)) { | |||||
385 | *alignment = bma; | |||||
386 | *ppCreateSet = BitVectorCreateSet; | |||||
387 | return bmsize; | |||||
388 | } | |||||
389 | else { | |||||
390 | *alignment = rla; | |||||
391 | *ppCreateSet = IntervalListCreateSet; | |||||
392 | return rlsize; | |||||
393 | } | |||||
394 | } | |||||
395 | ||||||
396 | /***************************************************************************/ | |||||
397 | ||||||
398 | /* user-visible functions */ | |||||
399 | ||||||
400 | int | |||||
401 | RecordSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals, | |||||
402 | int *alignment) | |||||
403 | { | |||||
404 | RecordCreateSetProcPtr pCreateSet; | |||||
405 | ||||||
406 | return _RecordSetMemoryRequirements(pIntervals, nIntervals, alignment, | |||||
407 | &pCreateSet); | |||||
408 | } | |||||
409 | ||||||
410 | RecordSetPtr | |||||
411 | RecordCreateSet(RecordSetInterval * pIntervals, int nIntervals, void *pMem, | |||||
412 | int memsize) | |||||
413 | { | |||||
414 | RecordCreateSetProcPtr pCreateSet; | |||||
415 | int alignment; | |||||
416 | int size; | |||||
417 | ||||||
418 | size = _RecordSetMemoryRequirements(pIntervals, nIntervals, &alignment, | |||||
419 | &pCreateSet); | |||||
420 | if (pMem) { | |||||
421 | if (((long) pMem & (alignment - 1)) || memsize < size) | |||||
422 | return NULL((void*)0); | |||||
423 | } | |||||
424 | return (*pCreateSet) (pIntervals, nIntervals, pMem, size); | |||||
425 | } |