Skip to content

Bypass broken fade-out path to eliminate double-free recursion - #49

Open
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/fade-out-double-free-bypass
Open

Bypass broken fade-out path to eliminate double-free recursion#49
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/fade-out-double-free-bypass

Conversation

@jEsuSdA

@jEsuSdA jEsuSdA commented Jul 2, 2026

Copy link
Copy Markdown

Summary

Bypasses the broken fade-out path in destroy_win() to eliminate a recursive double-free crash.

Problem

The fade-out path is broken:

  1. destroy_win() calls set_fade() with destroy_callback as the callback
  2. When the fade completes, dequeue_fade() calls destroy_callback()
  3. destroy_callback() calls finish_destroy_win()
  4. finish_destroy_win() calls cleanup_fade()
  5. cleanup_fade() calls dequeue_fade() again
  6. dequeue_fade() calls destroy_callback() again on the same win*
  7. finish_destroy_win() runs a second time on the freed/already-destroyed win*, causing a double-free / use-after-free

Solution

Since fading is already known to be broken and not maintained, the safest fix is to bypass the fade-out path entirely. destroy_win() now always calls finish_destroy_win() directly, and the unused destroy_callback is removed.

This eliminates the recursive double-free while keeping the code simpler. Note: fade-in (set_fade on map) is unaffected and continues to work if enabled.

Scope

  • Only fastcompmgr.c is touched
  • make clean && make produces zero warnings, zero errors

Impact

Eliminates a crash path during window destruction. No functional change for users who do not use fading (the default).

The fade-out path in destroy_win() is broken:

1. destroy_win() calls set_fade() with destroy_callback as the callback
2. When the fade completes, dequeue_fade() calls destroy_callback()
3. destroy_callback() calls finish_destroy_win()
4. finish_destroy_win() calls cleanup_fade()
5. cleanup_fade() calls dequeue_fade() again
6. dequeue_fade() calls destroy_callback() again on the same win*
7. finish_destroy_win() runs a second time on the freed/already-destroyed
   win*, causing a double-free / use-after-free

Since fading is already known to be broken and not maintained, the safest
fix is to bypass the fade-out path entirely. destroy_win() now always calls
finish_destroy_win() directly, and the unused destroy_callback is removed.

This eliminates the recursive double-free while keeping the code simpler.
Note: fade-in (set_fade on map) is unaffected and continues to work if
enabled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant