File: | dix/property.c |
Location: | line 271, column 9 |
Description: | Null pointer argument in call to memory copy function |
1 | /*********************************************************** | |||||
2 | ||||||
3 | Copyright 1987, 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 included in | |||||
12 | all copies or substantial portions of the Software. | |||||
13 | ||||||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||||
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
20 | ||||||
21 | Except as contained in this notice, the name of The Open Group shall not be | |||||
22 | used in advertising or otherwise to promote the sale, use or other dealings | |||||
23 | in this Software without prior written authorization from The Open Group. | |||||
24 | ||||||
25 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. | |||||
26 | ||||||
27 | All Rights Reserved | |||||
28 | ||||||
29 | Permission to use, copy, modify, and distribute this software and its | |||||
30 | documentation for any purpose and without fee is hereby granted, | |||||
31 | provided that the above copyright notice appear in all copies and that | |||||
32 | both that copyright notice and this permission notice appear in | |||||
33 | supporting documentation, and that the name of Digital not be | |||||
34 | used in advertising or publicity pertaining to distribution of the | |||||
35 | software without specific, written prior permission. | |||||
36 | ||||||
37 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |||||
38 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |||||
39 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |||||
40 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |||||
41 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |||||
42 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |||||
43 | SOFTWARE. | |||||
44 | ||||||
45 | ******************************************************************/ | |||||
46 | ||||||
47 | #ifdef HAVE_DIX_CONFIG_H1 | |||||
48 | #include <dix-config.h> | |||||
49 | #endif | |||||
50 | ||||||
51 | #include <X11/X.h> | |||||
52 | #include <X11/Xproto.h> | |||||
53 | #include "windowstr.h" | |||||
54 | #include "propertyst.h" | |||||
55 | #include "dixstruct.h" | |||||
56 | #include "dispatch.h" | |||||
57 | #include "swaprep.h" | |||||
58 | #include "xace.h" | |||||
59 | ||||||
60 | /***************************************************************** | |||||
61 | * Property Stuff | |||||
62 | * | |||||
63 | * dixLookupProperty, dixChangeProperty, DeleteProperty | |||||
64 | * | |||||
65 | * Properties belong to windows. The list of properties should not be | |||||
66 | * traversed directly. Instead, use the three functions listed above. | |||||
67 | * | |||||
68 | *****************************************************************/ | |||||
69 | ||||||
70 | #ifdef notdef | |||||
71 | static void | |||||
72 | PrintPropertys(WindowPtr pWin) | |||||
73 | { | |||||
74 | PropertyPtr pProp; | |||||
75 | int j; | |||||
76 | ||||||
77 | pProp = pWin->userProps; | |||||
78 | while (pProp) { | |||||
79 | ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type); | |||||
80 | ErrorF("[dix] property format: %d\n", pProp->format); | |||||
81 | ErrorF("[dix] property data: \n"); | |||||
82 | for (j = 0; j < (pProp->format / 8) * pProp->size; j++) | |||||
83 | ErrorF("[dix] %c\n", pProp->data[j]); | |||||
84 | pProp = pProp->next; | |||||
85 | } | |||||
86 | } | |||||
87 | #endif | |||||
88 | ||||||
89 | int | |||||
90 | dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName, | |||||
91 | ClientPtr client, Mask access_mode) | |||||
92 | { | |||||
93 | PropertyPtr pProp; | |||||
94 | int rc = BadMatch8; | |||||
95 | ||||||
96 | client->errorValue = propertyName; | |||||
97 | ||||||
98 | for (pProp = wUserProps(pWin)((pWin)->optional ? (pWin)->optional->userProps : (( void*)0)); pProp; pProp = pProp->next) | |||||
99 | if (pProp->propertyName == propertyName) | |||||
100 | break; | |||||
101 | ||||||
102 | if (pProp) | |||||
103 | rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode); | |||||
104 | *result = pProp; | |||||
105 | return rc; | |||||
106 | } | |||||
107 | ||||||
108 | static void | |||||
109 | deliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom) | |||||
110 | { | |||||
111 | xEvent event = { | |||||
112 | .u.property.window = pWin->drawable.id, | |||||
113 | .u.property.state = state, | |||||
114 | .u.property.atom = atom, | |||||
115 | .u.property.time = currentTime.milliseconds | |||||
116 | }; | |||||
117 | event.u.u.type = PropertyNotify28; | |||||
118 | DeliverEvents(pWin, &event, 1, (WindowPtr) NULL((void*)0)); | |||||
119 | } | |||||
120 | ||||||
121 | int | |||||
122 | ProcRotateProperties(ClientPtr client) | |||||
123 | { | |||||
124 | int i, j, delta, rc; | |||||
125 | ||||||
126 | REQUEST(xRotatePropertiesReq)xRotatePropertiesReq *stuff = (xRotatePropertiesReq *)client-> requestBuffer; | |||||
127 | WindowPtr pWin; | |||||
128 | Atom *atoms; | |||||
129 | PropertyPtr *props; /* array of pointer */ | |||||
130 | PropertyPtr pProp, saved; | |||||
131 | ||||||
132 | REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2)if (((sizeof(xRotatePropertiesReq) >> 2) > client-> req_len) || (((stuff->nAtoms << 2) >> 2) >= client->req_len) || ((((uint64_t) sizeof(xRotatePropertiesReq ) + (stuff->nAtoms << 2) + 3) >> 2) != (uint64_t ) client->req_len)) return(16); | |||||
133 | UpdateCurrentTime(); | |||||
134 | rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess(1<<8)); | |||||
135 | if (rc != Success0 || stuff->nAtoms <= 0) | |||||
136 | return rc; | |||||
137 | ||||||
138 | atoms = (Atom *) &stuff[1]; | |||||
139 | props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr))xreallocarray(((void*)0), (stuff->nAtoms), (sizeof(PropertyPtr ))); | |||||
140 | saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec))xreallocarray(((void*)0), (stuff->nAtoms), (sizeof(PropertyRec ))); | |||||
141 | if (!props || !saved) { | |||||
142 | rc = BadAlloc11; | |||||
143 | goto out; | |||||
144 | } | |||||
145 | ||||||
146 | for (i = 0; i < stuff->nAtoms; i++) { | |||||
147 | if (!ValidAtom(atoms[i])) { | |||||
148 | rc = BadAtom5; | |||||
149 | client->errorValue = atoms[i]; | |||||
150 | goto out; | |||||
151 | } | |||||
152 | for (j = i + 1; j < stuff->nAtoms; j++) | |||||
153 | if (atoms[j] == atoms[i]) { | |||||
154 | rc = BadMatch8; | |||||
155 | goto out; | |||||
156 | } | |||||
157 | ||||||
158 | rc = dixLookupProperty(&pProp, pWin, atoms[i], client, | |||||
159 | DixReadAccess(1<<0) | DixWriteAccess(1<<1)); | |||||
160 | if (rc != Success0) | |||||
161 | goto out; | |||||
162 | ||||||
163 | props[i] = pProp; | |||||
164 | saved[i] = *pProp; | |||||
165 | } | |||||
166 | delta = stuff->nPositions; | |||||
167 | ||||||
168 | /* If the rotation is a complete 360 degrees, then moving the properties | |||||
169 | around and generating PropertyNotify events should be skipped. */ | |||||
170 | ||||||
171 | if (abs(delta) % stuff->nAtoms) { | |||||
172 | while (delta < 0) /* faster if abs value is small */ | |||||
173 | delta += stuff->nAtoms; | |||||
174 | for (i = 0; i < stuff->nAtoms; i++) { | |||||
175 | j = (i + delta) % stuff->nAtoms; | |||||
176 | deliverPropertyNotifyEvent(pWin, PropertyNewValue0, atoms[i]); | |||||
177 | ||||||
178 | /* Preserve name and devPrivates */ | |||||
179 | props[j]->type = saved[i].type; | |||||
180 | props[j]->format = saved[i].format; | |||||
181 | props[j]->size = saved[i].size; | |||||
182 | props[j]->data = saved[i].data; | |||||
183 | } | |||||
184 | } | |||||
185 | out: | |||||
186 | free(saved); | |||||
187 | free(props); | |||||
188 | return rc; | |||||
189 | } | |||||
190 | ||||||
191 | int | |||||
192 | ProcChangeProperty(ClientPtr client) | |||||
193 | { | |||||
194 | WindowPtr pWin; | |||||
195 | char format, mode; | |||||
196 | unsigned long len; | |||||
197 | int sizeInBytes, totalSize, err; | |||||
198 | ||||||
199 | REQUEST(xChangePropertyReq)xChangePropertyReq *stuff = (xChangePropertyReq *)client-> requestBuffer; | |||||
200 | ||||||
201 | REQUEST_AT_LEAST_SIZE(xChangePropertyReq)if ((sizeof(xChangePropertyReq) >> 2) > client->req_len ) return(16); | |||||
202 | UpdateCurrentTime(); | |||||
203 | format = stuff->format; | |||||
204 | mode = stuff->mode; | |||||
205 | if ((mode != PropModeReplace0) && (mode != PropModeAppend2) && | |||||
206 | (mode != PropModePrepend1)) { | |||||
207 | client->errorValue = mode; | |||||
208 | return BadValue2; | |||||
209 | } | |||||
210 | if ((format != 8) && (format != 16) && (format != 32)) { | |||||
211 | client->errorValue = format; | |||||
212 | return BadValue2; | |||||
213 | } | |||||
214 | len = stuff->nUnits; | |||||
215 | if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq))) | |||||
216 | return BadLength16; | |||||
217 | sizeInBytes = format >> 3; | |||||
218 | totalSize = len * sizeInBytes; | |||||
219 | REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize)if (((sizeof(xChangePropertyReq) >> 2) > client-> req_len) || (((totalSize) >> 2) >= client->req_len ) || ((((uint64_t) sizeof(xChangePropertyReq) + (totalSize) + 3) >> 2) != (uint64_t) client->req_len)) return(16); | |||||
220 | ||||||
221 | err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess(1<<8)); | |||||
222 | if (err != Success0) | |||||
223 | return err; | |||||
224 | if (!ValidAtom(stuff->property)) { | |||||
225 | client->errorValue = stuff->property; | |||||
226 | return BadAtom5; | |||||
227 | } | |||||
228 | if (!ValidAtom(stuff->type)) { | |||||
229 | client->errorValue = stuff->type; | |||||
230 | return BadAtom5; | |||||
231 | } | |||||
232 | ||||||
233 | err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type, | |||||
234 | (int) format, (int) mode, len, &stuff[1], | |||||
235 | TRUE1); | |||||
236 | if (err != Success0) | |||||
237 | return err; | |||||
238 | else | |||||
239 | return Success0; | |||||
240 | } | |||||
241 | ||||||
242 | int | |||||
243 | dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, | |||||
244 | Atom type, int format, int mode, unsigned long len, | |||||
245 | void *value, Bool sendevent) | |||||
246 | { | |||||
247 | PropertyPtr pProp; | |||||
248 | PropertyRec savedProp; | |||||
249 | int sizeInBytes, totalSize, rc; | |||||
250 | unsigned char *data; | |||||
251 | Mask access_mode; | |||||
252 | ||||||
253 | sizeInBytes = format >> 3; | |||||
254 | totalSize = len * sizeInBytes; | |||||
255 | access_mode = (mode == PropModeReplace0) ? DixWriteAccess(1<<1) : DixBlendAccess(1<<16); | |||||
256 | ||||||
257 | /* first see if property already exists */ | |||||
258 | rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode); | |||||
259 | ||||||
260 | if (rc == BadMatch8) { /* just add to list */ | |||||
261 | if (!pWin->optional && !MakeWindowOptional(pWin)) | |||||
262 | return BadAlloc11; | |||||
263 | pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY)(PropertyRec *) _dixAllocateObjectWithPrivates(sizeof(PropertyRec ), sizeof(PropertyRec), __builtin_offsetof(PropertyRec, devPrivates ), PRIVATE_PROPERTY); | |||||
264 | if (!pProp) | |||||
265 | return BadAlloc11; | |||||
266 | data = malloc(totalSize); | |||||
267 | if (!data && len) { | |||||
268 | dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY)_dixFreeObjectWithPrivates(pProp, (pProp)->devPrivates, PRIVATE_PROPERTY ); | |||||
269 | return BadAlloc11; | |||||
270 | } | |||||
271 | memcpy(data, value, totalSize)__builtin___memcpy_chk (data, value, totalSize, __builtin_object_size (data, 0)); | |||||
| ||||||
272 | pProp->propertyName = property; | |||||
273 | pProp->type = type; | |||||
274 | pProp->format = format; | |||||
275 | pProp->data = data; | |||||
276 | pProp->size = len; | |||||
277 | rc = XaceHookPropertyAccess(pClient, pWin, &pProp, | |||||
278 | DixCreateAccess(1<<3) | DixWriteAccess(1<<1)); | |||||
279 | if (rc != Success0) { | |||||
280 | free(data); | |||||
281 | dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY)_dixFreeObjectWithPrivates(pProp, (pProp)->devPrivates, PRIVATE_PROPERTY ); | |||||
282 | pClient->errorValue = property; | |||||
283 | return rc; | |||||
284 | } | |||||
285 | pProp->next = pWin->optional->userProps; | |||||
286 | pWin->optional->userProps = pProp; | |||||
287 | } | |||||
288 | else if (rc == Success0) { | |||||
289 | /* To append or prepend to a property the request format and type | |||||
290 | must match those of the already defined property. The | |||||
291 | existing format and type are irrelevant when using the mode | |||||
292 | "PropModeReplace" since they will be written over. */ | |||||
293 | ||||||
294 | if ((format != pProp->format) && (mode != PropModeReplace0)) | |||||
295 | return BadMatch8; | |||||
296 | if ((pProp->type != type) && (mode != PropModeReplace0)) | |||||
297 | return BadMatch8; | |||||
298 | ||||||
299 | /* save the old values for later */ | |||||
300 | savedProp = *pProp; | |||||
301 | ||||||
302 | if (mode == PropModeReplace0) { | |||||
303 | data = malloc(totalSize); | |||||
304 | if (!data && len) | |||||
305 | return BadAlloc11; | |||||
306 | memcpy(data, value, totalSize)__builtin___memcpy_chk (data, value, totalSize, __builtin_object_size (data, 0)); | |||||
307 | pProp->data = data; | |||||
308 | pProp->size = len; | |||||
309 | pProp->type = type; | |||||
310 | pProp->format = format; | |||||
311 | } | |||||
312 | else if (len == 0) { | |||||
313 | /* do nothing */ | |||||
314 | } | |||||
315 | else if (mode == PropModeAppend2) { | |||||
316 | data = xallocarray(pProp->size + len, sizeInBytes)xreallocarray(((void*)0), (pProp->size + len), (sizeInBytes )); | |||||
317 | if (!data) | |||||
318 | return BadAlloc11; | |||||
319 | memcpy(data, pProp->data, pProp->size * sizeInBytes)__builtin___memcpy_chk (data, pProp->data, pProp->size * sizeInBytes, __builtin_object_size (data, 0)); | |||||
320 | memcpy(data + pProp->size * sizeInBytes, value, totalSize)__builtin___memcpy_chk (data + pProp->size * sizeInBytes, value , totalSize, __builtin_object_size (data + pProp->size * sizeInBytes , 0)); | |||||
321 | pProp->data = data; | |||||
322 | pProp->size += len; | |||||
323 | } | |||||
324 | else if (mode == PropModePrepend1) { | |||||
325 | data = xallocarray(len + pProp->size, sizeInBytes)xreallocarray(((void*)0), (len + pProp->size), (sizeInBytes )); | |||||
326 | if (!data) | |||||
327 | return BadAlloc11; | |||||
328 | memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes)__builtin___memcpy_chk (data + totalSize, pProp->data, pProp ->size * sizeInBytes, __builtin_object_size (data + totalSize , 0)); | |||||
329 | memcpy(data, value, totalSize)__builtin___memcpy_chk (data, value, totalSize, __builtin_object_size (data, 0)); | |||||
330 | pProp->data = data; | |||||
331 | pProp->size += len; | |||||
332 | } | |||||
333 | ||||||
334 | /* Allow security modules to check the new content */ | |||||
335 | access_mode |= DixPostAccess(1<<28); | |||||
336 | rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode); | |||||
337 | if (rc == Success0) { | |||||
338 | if (savedProp.data != pProp->data) | |||||
339 | free(savedProp.data); | |||||
340 | } | |||||
341 | else { | |||||
342 | if (savedProp.data != pProp->data) | |||||
343 | free(pProp->data); | |||||
344 | *pProp = savedProp; | |||||
345 | return rc; | |||||
346 | } | |||||
347 | } | |||||
348 | else | |||||
349 | return rc; | |||||
350 | ||||||
351 | if (sendevent) | |||||
352 | deliverPropertyNotifyEvent(pWin, PropertyNewValue0, pProp->propertyName); | |||||
353 | ||||||
354 | return Success0; | |||||
355 | } | |||||
356 | ||||||
357 | int | |||||
358 | ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, | |||||
359 | int mode, unsigned long len, void *value, Bool sendevent) | |||||
360 | { | |||||
361 | return dixChangeWindowProperty(serverClient, pWin, property, type, format, | |||||
| ||||||
362 | mode, len, value, sendevent); | |||||
363 | } | |||||
364 | ||||||
365 | int | |||||
366 | DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) | |||||
367 | { | |||||
368 | PropertyPtr pProp, prevProp; | |||||
369 | int rc; | |||||
370 | ||||||
371 | rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess(1<<2)); | |||||
372 | if (rc == BadMatch8) | |||||
373 | return Success0; /* Succeed if property does not exist */ | |||||
374 | ||||||
375 | if (rc == Success0) { | |||||
376 | if (pWin->optional->userProps == pProp) { | |||||
377 | /* Takes care of head */ | |||||
378 | if (!(pWin->optional->userProps = pProp->next)) | |||||
379 | CheckWindowOptionalNeed(pWin); | |||||
380 | } | |||||
381 | else { | |||||
382 | /* Need to traverse to find the previous element */ | |||||
383 | prevProp = pWin->optional->userProps; | |||||
384 | while (prevProp->next != pProp) | |||||
385 | prevProp = prevProp->next; | |||||
386 | prevProp->next = pProp->next; | |||||
387 | } | |||||
388 | ||||||
389 | deliverPropertyNotifyEvent(pWin, PropertyDelete1, pProp->propertyName); | |||||
390 | free(pProp->data); | |||||
391 | dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY)_dixFreeObjectWithPrivates(pProp, (pProp)->devPrivates, PRIVATE_PROPERTY ); | |||||
392 | } | |||||
393 | return rc; | |||||
394 | } | |||||
395 | ||||||
396 | void | |||||
397 | DeleteAllWindowProperties(WindowPtr pWin) | |||||
398 | { | |||||
399 | PropertyPtr pProp, pNextProp; | |||||
400 | ||||||
401 | pProp = wUserProps(pWin)((pWin)->optional ? (pWin)->optional->userProps : (( void*)0)); | |||||
402 | while (pProp) { | |||||
403 | deliverPropertyNotifyEvent(pWin, PropertyDelete1, pProp->propertyName); | |||||
404 | pNextProp = pProp->next; | |||||
405 | free(pProp->data); | |||||
406 | dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY)_dixFreeObjectWithPrivates(pProp, (pProp)->devPrivates, PRIVATE_PROPERTY ); | |||||
407 | pProp = pNextProp; | |||||
408 | } | |||||
409 | ||||||
410 | if (pWin->optional) | |||||
411 | pWin->optional->userProps = NULL((void*)0); | |||||
412 | } | |||||
413 | ||||||
414 | static int | |||||
415 | NullPropertyReply(ClientPtr client, ATOM propertyType, int format) | |||||
416 | { | |||||
417 | xGetPropertyReply reply = { | |||||
418 | .type = X_Reply1, | |||||
419 | .format = format, | |||||
420 | .sequenceNumber = client->sequence, | |||||
421 | .length = 0, | |||||
422 | .propertyType = propertyType, | |||||
423 | .bytesAfter = 0, | |||||
424 | .nItems = 0 | |||||
425 | }; | |||||
426 | WriteReplyToClient(client, sizeof(xGenericReply), &reply){ if ((client)->swapped) (*ReplySwapVector[((xReq *)(client )->requestBuffer)->reqType]) (client, (int)(sizeof(xGenericReply )), &reply); else WriteToClient(client, (int)(sizeof(xGenericReply )), (&reply)); }; | |||||
427 | return Success0; | |||||
428 | } | |||||
429 | ||||||
430 | /***************** | |||||
431 | * GetProperty | |||||
432 | * If type Any is specified, returns the property from the specified | |||||
433 | * window regardless of its type. If a type is specified, returns the | |||||
434 | * property only if its type equals the specified type. | |||||
435 | * If delete is True and a property is returned, the property is also | |||||
436 | * deleted from the window and a PropertyNotify event is generated on the | |||||
437 | * window. | |||||
438 | *****************/ | |||||
439 | ||||||
440 | int | |||||
441 | ProcGetProperty(ClientPtr client) | |||||
442 | { | |||||
443 | PropertyPtr pProp, prevProp; | |||||
444 | unsigned long n, len, ind; | |||||
445 | int rc; | |||||
446 | WindowPtr pWin; | |||||
447 | xGetPropertyReply reply; | |||||
448 | Mask win_mode = DixGetPropAccess(1<<7), prop_mode = DixReadAccess(1<<0); | |||||
449 | ||||||
450 | REQUEST(xGetPropertyReq)xGetPropertyReq *stuff = (xGetPropertyReq *)client->requestBuffer; | |||||
451 | ||||||
452 | REQUEST_SIZE_MATCH(xGetPropertyReq)if ((sizeof(xGetPropertyReq) >> 2) != client->req_len ) return(16); | |||||
453 | if (stuff->delete) { | |||||
454 | UpdateCurrentTime(); | |||||
455 | win_mode |= DixSetPropAccess(1<<8); | |||||
456 | prop_mode |= DixDestroyAccess(1<<2); | |||||
457 | } | |||||
458 | rc = dixLookupWindow(&pWin, stuff->window, client, win_mode); | |||||
459 | if (rc != Success0) | |||||
460 | return rc; | |||||
461 | ||||||
462 | if (!ValidAtom(stuff->property)) { | |||||
463 | client->errorValue = stuff->property; | |||||
464 | return BadAtom5; | |||||
465 | } | |||||
466 | if ((stuff->delete != xTrue1) && (stuff->delete != xFalse0)) { | |||||
467 | client->errorValue = stuff->delete; | |||||
468 | return BadValue2; | |||||
469 | } | |||||
470 | if ((stuff->type != AnyPropertyType0L) && !ValidAtom(stuff->type)) { | |||||
471 | client->errorValue = stuff->type; | |||||
472 | return BadAtom5; | |||||
473 | } | |||||
474 | ||||||
475 | rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode); | |||||
476 | if (rc == BadMatch8) | |||||
477 | return NullPropertyReply(client, None0L, 0); | |||||
478 | else if (rc != Success0) | |||||
479 | return rc; | |||||
480 | ||||||
481 | /* If the request type and actual type don't match. Return the | |||||
482 | property information, but not the data. */ | |||||
483 | ||||||
484 | if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType0L)) | |||||
485 | ) { | |||||
486 | reply = (xGetPropertyReply) { | |||||
487 | .type = X_Reply1, | |||||
488 | .sequenceNumber = client->sequence, | |||||
489 | .bytesAfter = pProp->size, | |||||
490 | .format = pProp->format, | |||||
491 | .length = 0, | |||||
492 | .nItems = 0, | |||||
493 | .propertyType = pProp->type | |||||
494 | }; | |||||
495 | WriteReplyToClient(client, sizeof(xGenericReply), &reply){ if ((client)->swapped) (*ReplySwapVector[((xReq *)(client )->requestBuffer)->reqType]) (client, (int)(sizeof(xGenericReply )), &reply); else WriteToClient(client, (int)(sizeof(xGenericReply )), (&reply)); }; | |||||
496 | return Success0; | |||||
497 | } | |||||
498 | ||||||
499 | /* | |||||
500 | * Return type, format, value to client | |||||
501 | */ | |||||
502 | n = (pProp->format / 8) * pProp->size; /* size (bytes) of prop */ | |||||
503 | ind = stuff->longOffset << 2; | |||||
504 | ||||||
505 | /* If longOffset is invalid such that it causes "len" to | |||||
506 | be negative, it's a value error. */ | |||||
507 | ||||||
508 | if (n < ind) { | |||||
509 | client->errorValue = stuff->longOffset; | |||||
510 | return BadValue2; | |||||
511 | } | |||||
512 | ||||||
513 | len = min(n - ind, 4 * stuff->longLength)(((n - ind) < (4 * stuff->longLength)) ? (n - ind) : (4 * stuff->longLength)); | |||||
514 | ||||||
515 | reply = (xGetPropertyReply) { | |||||
516 | .type = X_Reply1, | |||||
517 | .sequenceNumber = client->sequence, | |||||
518 | .bytesAfter = n - (ind + len), | |||||
519 | .format = pProp->format, | |||||
520 | .length = bytes_to_int32(len), | |||||
521 | .nItems = len / (pProp->format / 8), | |||||
522 | .propertyType = pProp->type | |||||
523 | }; | |||||
524 | ||||||
525 | if (stuff->delete && (reply.bytesAfter == 0)) | |||||
526 | deliverPropertyNotifyEvent(pWin, PropertyDelete1, pProp->propertyName); | |||||
527 | ||||||
528 | WriteReplyToClient(client, sizeof(xGenericReply), &reply){ if ((client)->swapped) (*ReplySwapVector[((xReq *)(client )->requestBuffer)->reqType]) (client, (int)(sizeof(xGenericReply )), &reply); else WriteToClient(client, (int)(sizeof(xGenericReply )), (&reply)); }; | |||||
529 | if (len) { | |||||
530 | switch (reply.format) { | |||||
531 | case 32: | |||||
532 | client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; | |||||
533 | break; | |||||
534 | case 16: | |||||
535 | client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; | |||||
536 | break; | |||||
537 | default: | |||||
538 | client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; | |||||
539 | break; | |||||
540 | } | |||||
541 | WriteSwappedDataToClient(client, len, (char *) pProp->data + ind)if ((client)->swapped) (*(client)->pSwapReplyFunc)(client , (int)(len), (char *) pProp->data + ind); else WriteToClient (client, (int)(len), ((char *) pProp->data + ind));; | |||||
542 | } | |||||
543 | ||||||
544 | if (stuff->delete && (reply.bytesAfter == 0)) { | |||||
545 | /* Delete the Property */ | |||||
546 | if (pWin->optional->userProps == pProp) { | |||||
547 | /* Takes care of head */ | |||||
548 | if (!(pWin->optional->userProps = pProp->next)) | |||||
549 | CheckWindowOptionalNeed(pWin); | |||||
550 | } | |||||
551 | else { | |||||
552 | /* Need to traverse to find the previous element */ | |||||
553 | prevProp = pWin->optional->userProps; | |||||
554 | while (prevProp->next != pProp) | |||||
555 | prevProp = prevProp->next; | |||||
556 | prevProp->next = pProp->next; | |||||
557 | } | |||||
558 | ||||||
559 | free(pProp->data); | |||||
560 | dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY)_dixFreeObjectWithPrivates(pProp, (pProp)->devPrivates, PRIVATE_PROPERTY ); | |||||
561 | } | |||||
562 | return Success0; | |||||
563 | } | |||||
564 | ||||||
565 | int | |||||
566 | ProcListProperties(ClientPtr client) | |||||
567 | { | |||||
568 | Atom *pAtoms = NULL((void*)0), *temppAtoms; | |||||
569 | xListPropertiesReply xlpr; | |||||
570 | int rc, numProps = 0; | |||||
571 | WindowPtr pWin; | |||||
572 | PropertyPtr pProp, realProp; | |||||
573 | ||||||
574 | REQUEST(xResourceReq)xResourceReq *stuff = (xResourceReq *)client->requestBuffer; | |||||
575 | ||||||
576 | REQUEST_SIZE_MATCH(xResourceReq)if ((sizeof(xResourceReq) >> 2) != client->req_len) return (16); | |||||
577 | rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess(1<<6)); | |||||
578 | if (rc != Success0) | |||||
579 | return rc; | |||||
580 | ||||||
581 | for (pProp = wUserProps(pWin)((pWin)->optional ? (pWin)->optional->userProps : (( void*)0)); pProp; pProp = pProp->next) | |||||
582 | numProps++; | |||||
583 | ||||||
584 | if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom))xreallocarray(((void*)0), (numProps), (sizeof(Atom))))) | |||||
585 | return BadAlloc11; | |||||
586 | ||||||
587 | numProps = 0; | |||||
588 | temppAtoms = pAtoms; | |||||
589 | for (pProp = wUserProps(pWin)((pWin)->optional ? (pWin)->optional->userProps : (( void*)0)); pProp; pProp = pProp->next) { | |||||
590 | realProp = pProp; | |||||
591 | rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess(1<<4)); | |||||
592 | if (rc == Success0 && realProp == pProp) { | |||||
593 | *temppAtoms++ = pProp->propertyName; | |||||
594 | numProps++; | |||||
595 | } | |||||
596 | } | |||||
597 | ||||||
598 | xlpr = (xListPropertiesReply) { | |||||
599 | .type = X_Reply1, | |||||
600 | .sequenceNumber = client->sequence, | |||||
601 | .length = bytes_to_int32(numProps * sizeof(Atom)), | |||||
602 | .nProperties = numProps | |||||
603 | }; | |||||
604 | WriteReplyToClient(client, sizeof(xGenericReply), &xlpr){ if ((client)->swapped) (*ReplySwapVector[((xReq *)(client )->requestBuffer)->reqType]) (client, (int)(sizeof(xGenericReply )), &xlpr); else WriteToClient(client, (int)(sizeof(xGenericReply )), (&xlpr)); }; | |||||
605 | if (numProps) { | |||||
606 | client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; | |||||
607 | WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms)if ((client)->swapped) (*(client)->pSwapReplyFunc)(client , (int)(numProps * sizeof(Atom)), pAtoms); else WriteToClient (client, (int)(numProps * sizeof(Atom)), (pAtoms));; | |||||
608 | } | |||||
609 | free(pAtoms); | |||||
610 | return Success0; | |||||
611 | } | |||||
612 | ||||||
613 | int | |||||
614 | ProcDeleteProperty(ClientPtr client) | |||||
615 | { | |||||
616 | WindowPtr pWin; | |||||
617 | ||||||
618 | REQUEST(xDeletePropertyReq)xDeletePropertyReq *stuff = (xDeletePropertyReq *)client-> requestBuffer; | |||||
619 | int result; | |||||
620 | ||||||
621 | REQUEST_SIZE_MATCH(xDeletePropertyReq)if ((sizeof(xDeletePropertyReq) >> 2) != client->req_len ) return(16); | |||||
622 | UpdateCurrentTime(); | |||||
623 | result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess(1<<8)); | |||||
624 | if (result != Success0) | |||||
625 | return result; | |||||
626 | if (!ValidAtom(stuff->property)) { | |||||
627 | client->errorValue = stuff->property; | |||||
628 | return BadAtom5; | |||||
629 | } | |||||
630 | ||||||
631 | return DeleteProperty(client, pWin, stuff->property); | |||||
632 | } |