From 390f33a0f94a47fbdc486834a0ac67d6b8b14328 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Wed, 24 Sep 2025 17:49:03 +0200 Subject: [PATCH] fix use after free --- application/atomic.h | 70 ++++++++++++++++++++++++++++++++++++++++++++ application/main.c | 2 +- application/player.c | 32 +++++++++++++------- application/player.h | 2 +- application/window.c | 2 +- application/window.h | 2 ++ 6 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 application/atomic.h diff --git a/application/atomic.h b/application/atomic.h new file mode 100644 index 0000000..ab684e1 --- /dev/null +++ b/application/atomic.h @@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ATOMIC_H +#define ATOMIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __gnu_linux__ + +#define ws_atomic_inc32(intptr) __sync_fetch_and_add(intptr, 1) +#define ws_atomic_dec32(intptr) __sync_fetch_and_sub(intptr, 1) - 1 +#define ws_atomic_add32(intptr, val) __sync_fetch_and_add(intptr, val) +#define ws_atomic_sub32(intptr, val) __sync_fetch_and_sub(intptr, val) + +#elif defined(OSX) +#include + +#define ws_atomic_inc32(intptr) OSAtomicIncrement32((volatile int32_t *)intptr) +#define ws_atomic_dec32(intptr) OSAtomicDecrement32((volatile int32_t *)intptr) + +#elif defined(BSD) +#define ws_atomic_inc32(intptr) __sync_fetch_and_add(intptr, 1) +#define ws_atomic_dec32(intptr) __sync_fetch_and_sub(intptr, 1) - 1 +#define ws_atomic_add32(intptr, val) __sync_fetch_and_add(intptr, val) +#define ws_atomic_sub32(intptr, val) __sync_fetch_and_sub(intptr, va +#else +// use atomic.h +#include + +#define ws_atomic_inc32(intptr) atomic_inc_32_nv(intptr) +#define ws_atomic_dec32(intptr) atomic_dec_32_nv(intptr) +// TODO + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* ATOMIC_H */ + diff --git a/application/main.c b/application/main.c index 8cf02c4..1205d4d 100644 --- a/application/main.c +++ b/application/main.c @@ -222,7 +222,7 @@ int main(int argc, char** argv) { // and enable the single instance mode if possible XmToggleButtonGadgetSetState(window->prefSingleInstanceButton, True, True); } - + WindowShow(window); AppMainLoop(app); diff --git a/application/player.c b/application/player.c index 0eced5f..6ff7377 100644 --- a/application/player.c +++ b/application/player.c @@ -43,6 +43,8 @@ #include "settings.h" #include "playlist.h" +#include "atomic.h" + extern char **environ; #define STR_BUFSIZE 512 @@ -112,9 +114,11 @@ static void* wait_for_process(void *data) { printf("waitpid: %d\n", status); + printf("wait_for_process player: %p\n", player); player->isactive = FALSE; player->status = status; SetPlayerWindow(0); + PlayerUnref(player); return NULL; } @@ -170,9 +174,11 @@ static int start_player_process(Player *player, MainWindow *win) { player->process = player_pid; player->isactive = TRUE; + player->ref++; pthread_t tid; if(pthread_create(&tid, NULL, wait_for_process, player)) { perror("pthread_create"); + player->ref--; } return 0; @@ -253,28 +259,29 @@ static void* start_player(void *data) { Player *player = malloc(sizeof(Player)); memset(player, 0, sizeof(Player)); + player->ref = 1; // start mpv if(start_player_process(player, win)) { - PlayerDestroy(player); + PlayerUnref(player); return NULL; } // wait until IPC socket is ready if(wait_for_ipc(player)) { - PlayerDestroy(player); + PlayerUnref(player); return NULL; } //close(player->log); if(connect_to_ipc(player)) { - PlayerDestroy(player); + PlayerUnref(player); return NULL; } // set player in main window if(win->player) { - PlayerDestroy(win->player); + PlayerUnref(win->player); } win->player = player; @@ -495,23 +502,28 @@ static void handle_json_rpc_event(Player *p, JSONValue *v, JSONValue *event) { } } -void PlayerDestroy(Player *p) { +void PlayerUnref(Player *p) { if(p->log >= 0) { close(p->log); + p->log = -1; } if(p->ipc >= 0) { close(p->ipc); - } - - if(p->tmp) { - free(p->tmp); + p->ipc = -1; } if(p->isactive) { kill(p->process, SIGTERM); } + if(ws_atomic_dec32(&p->ref) > 0) { + return; + } - SetPlayerWindow(0); + if(p->tmp) { + free(p->tmp); + } + + SetPlayerWindow(0); free(p); } diff --git a/application/player.h b/application/player.h index 8f47e83..4fd05f8 100644 --- a/application/player.h +++ b/application/player.h @@ -40,7 +40,7 @@ extern "C" { void PlayerOpenFile(MainWindow *win); -void PlayerDestroy(Player *p); +void PlayerUnref(Player *p); void PlayerEOF(Player *p); diff --git a/application/window.c b/application/window.c index 4adac0e..5777c8f 100644 --- a/application/window.c +++ b/application/window.c @@ -761,7 +761,7 @@ void WindowAdjustAspectRatio(MainWindow *win) { void WindowClosePlayer(MainWindow *win) { if(win->player) { - PlayerDestroy(win->player); + PlayerUnref(win->player); } win->player = NULL; WindowShowPlayerCursor(win); diff --git a/application/window.h b/application/window.h index dd7d3fe..7df9825 100644 --- a/application/window.h +++ b/application/window.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ typedef struct Player { int width; int height; int osd_height; + uint32_t ref; } Player; typedef struct { -- 2.47.3