summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSultan Alsawaf <sultan@kerneltoast.com>2023-01-22 20:59:32 -0800
committerSultan Alsawaf <sultan@kerneltoast.com>2023-02-28 22:43:37 -0800
commit35975d90546931de10b014a222a6051f34c62e57 (patch)
tree71c2eb701b5d34b59417c18b53c59d7da45195ab
parentbe864d8e185fe9e699fa661e70e02b319384dee6 (diff)
downloadxserver-35975d90546931de10b014a222a6051f34c62e57.tar.gz
modesetting: Fix memory leak on ms_do_pageflip error
The event allocation for ms_do_pageflip is leaked on error because callers of ms_do_pageflip have no way of knowing whether or not a page flip succeeded for any CRTCs. If a page flip succeeded for at least one CRTC, then it's not safe for the caller to free the event allocation, and the allocation won't be leaked. The event allocation is only leaked when not a single CRTC's page flip succeeded. Since all callers of ms_do_pageflip allocate the event pointer, and all of them intentionally leak the event allocation when ms_do_pageflip returns an error, just free the event pointer inside ms_do_pageflip when a page flip doesn't succeed for any CRTC. Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com> Reviewed-by: Martin Roukala <martin.roukala@mupuf.org>
-rw-r--r--hw/xfree86/drivers/modesetting/pageflip.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c
index 08a1bcd31..94437c0f3 100644
--- a/hw/xfree86/drivers/modesetting/pageflip.c
+++ b/hw/xfree86/drivers/modesetting/pageflip.c
@@ -336,7 +336,7 @@ ms_do_pageflip(ScreenPtr screen,
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s: Failed to get GBM BO for flip to new front.\n",
log_prefix);
- return FALSE;
+ goto error_free_event;
}
flipdata = calloc(1, sizeof(struct ms_flipdata));
@@ -344,7 +344,7 @@ ms_do_pageflip(ScreenPtr screen,
drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s: Failed to allocate flipdata.\n", log_prefix);
- return FALSE;
+ goto error_free_event;
}
flipdata->event = event;
@@ -465,11 +465,16 @@ error_out:
drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
/* if only the local reference - free the structure,
* else drop the local reference and return */
- if (flipdata->flip_count == 1)
+ if (flipdata->flip_count == 1) {
free(flipdata);
- else
+ } else {
flipdata->flip_count--;
+ return FALSE;
+ }
+error_free_event:
+ /* Free the event since the caller has no way to know it's safe to free */
+ free(event);
return FALSE;
}