| 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 | } |