Jinoh Kang (@iamahuman) commented about dlls/win32u/input.c:
- SERVER_START_REQ( set_cursor ) + while (get_shared_desktop( &lock )) { - if ((ret = !wine_server_call( req ))) + SHARED_READ_BEGIN( &lock.shared->desktop, desktop_shm_t ) { - pt->x = reply->new_x; - pt->y = reply->new_y; - last_change = reply->last_change; + if ((valid = lock.id == shared->obj.id)) + { + pt->x = shared->cursor.x; + pt->y = shared->cursor.y; + last_change = shared->cursor.last_change; + ret = TRUE;
If the current shared-read iteration fails due to destroyed object, `ret = TRUE` will live on even if the next iteration sets `valid = FALSE`. This is kept as-is if `get_shared_desktop()` returned NULL. In general, the number of shared read retries shouldn't affect the outcome of the loop. This means that any variables *conditionally*[^1] written by the read critical section should be considered unknown / garbage.[^2] [^1]: `valid` is unconditionally written. [^2]: Rule of thumb: a read section should *always* write to a variable or not at all. If a variable is ever written, it should be read *only after* it has been written in the current iteration. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/3103#note_63376