Hello Andreas, * Andreas Schwab wrote on Mon, Mar 03, 2008 at 03:39:47PM CET: > libltdl uses memory after free when initialized twice.
Thank you very much for the bug report. Proposed patch below. I tested it on i686-unknown-linux-gnu but it should be tested with as many loaders as possible. So I'd appreciate a review of this, and also test results on systems with loaders other than preopen and dlopen. (I haven't even tested successful compilation on those other systems.) Thanks, Ralf 2008-03-03 Ralf Wildenhues <[EMAIL PROTECTED]> * libltdl/loaders/dld_link.c (vl_exit): New function, zero out ... (vtable): ... this new file static variable split out from ... (get_vtable): ... here. Initialize vtable, register vl_exit as dlloader_exit function. * libltdl/loaders/dlopen.c: Likewise. * libltdl/loaders/dyld.c: Likewise. * libltdl/loaders/load_add_on.c: Likewise. * libltdl/loaders/loadlibrary.c: Likewise. * libltdl/loaders/shl_load.c: Likewise. * libltdl/loaders/preopen.c: Likewise; vl_exit existed here already * tests/lt_dlexit.at (lt_dlexit unloading libs): Update test. Report by Andreas Schwab. Index: libltdl/loaders/dld_link.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/dld_link.c,v retrieving revision 1.9 diff -u -r1.9 dld_link.c --- libltdl/loaders/dld_link.c 8 May 2007 14:38:50 -0000 1.9 +++ libltdl/loaders/dld_link.c 3 Mar 2008 21:41:03 -0000 @@ -1,7 +1,7 @@ /* loader-dld_link.c -- dynamic linking with dld Copyright (C) 1998, 1999, 2000, 2004, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Thomas Tanner, 1998 NOTE: The canonical source of this file is maintained with the @@ -45,20 +45,21 @@ /* Boilerplate code to set up the vtable for hooking this loader into libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); static lt_module vm_open (lt_user_data loader_data, const char *filename, lt_dladvise advise); static int vm_close (lt_user_data loader_data, lt_module module); static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = lt__zalloc (sizeof *vtable); @@ -70,6 +71,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_APPEND; } @@ -92,6 +94,15 @@ # include <dld.h> #endif +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + /* A function called through the vtable to open a module with this loader. Returns an opaque representation of the newly opened module for processing with this loader's other vtable functions. */ Index: libltdl/loaders/dlopen.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/dlopen.c,v retrieving revision 1.12 diff -u -r1.12 dlopen.c --- libltdl/loaders/dlopen.c 12 Jan 2008 17:00:51 -0000 1.12 +++ libltdl/loaders/dlopen.c 3 Mar 2008 21:41:03 -0000 @@ -45,20 +45,21 @@ /* Boilerplate code to set up the vtable for hooking this loader into libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); static lt_module vm_open (lt_user_data loader_data, const char *filename, lt_dladvise advise); static int vm_close (lt_user_data loader_data, lt_module module); static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); @@ -73,6 +74,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_PREPEND; } @@ -146,6 +148,17 @@ #define DL__SETERROR(errorcode) \ LT__SETERRORSTR (DLERROR (errorcode)) + +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + + /* A function called through the vtable to open a module with this loader. Returns an opaque representation of the newly opened module for processing with this loader's other vtable functions. */ Index: libltdl/loaders/dyld.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/dyld.c,v retrieving revision 1.9 diff -u -r1.9 dyld.c --- libltdl/loaders/dyld.c 4 Jul 2007 23:05:05 -0000 1.9 +++ libltdl/loaders/dyld.c 3 Mar 2008 21:41:04 -0000 @@ -1,7 +1,7 @@ /* loader-dyld.c -- dynamic linking on darwin and OS X Copyright (C) 1998, 1999, 2000, 2004, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Peter O'Gorman, 1998 NOTE: The canonical source of this file is maintained with the @@ -53,14 +53,14 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = lt__zalloc (sizeof *vtable); @@ -74,6 +74,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_APPEND; } @@ -181,6 +182,15 @@ static int dyld_cannot_close = 0; +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + /* A function called through the vtable to initialise this loader. */ static int vl_init (lt_user_data loader_data) Index: libltdl/loaders/load_add_on.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/load_add_on.c,v retrieving revision 1.9 diff -u -r1.9 load_add_on.c --- libltdl/loaders/load_add_on.c 8 May 2007 14:38:50 -0000 1.9 +++ libltdl/loaders/load_add_on.c 3 Mar 2008 21:41:04 -0000 @@ -1,7 +1,7 @@ /* loader-load_add_on.c -- dynamic linking for BeOS Copyright (C) 1998, 1999, 2000, 2004, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Thomas Tanner, 1998 NOTE: The canonical source of this file is maintained with the @@ -45,20 +45,21 @@ /* Boilerplate code to set up the vtable for hooking this loader into libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); static lt_module vm_open (lt_user_data loader_data, const char *filename, lt_dladvise advise); static int vm_close (lt_user_data loader_data, lt_module module); static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = lt__zalloc (sizeof *vtable); @@ -70,6 +71,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_APPEND; } @@ -90,6 +92,15 @@ #include <kernel/image.h> +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + /* A function called through the vtable to open a module with this loader. Returns an opaque representation of the newly opened module for processing with this loader's other vtable functions. */ Index: libltdl/loaders/loadlibrary.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/loadlibrary.c,v retrieving revision 1.15 diff -u -r1.15 loadlibrary.c --- libltdl/loaders/loadlibrary.c 8 May 2007 14:38:50 -0000 1.15 +++ libltdl/loaders/loadlibrary.c 3 Mar 2008 21:41:04 -0000 @@ -1,7 +1,7 @@ /* loader-loadlibrary.c -- dynamic linking for Win32 Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Thomas Tanner, 1998 NOTE: The canonical source of this file is maintained with the @@ -49,6 +49,7 @@ /* Boilerplate code to set up the vtable for hooking this loader into libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); static lt_module vm_open (lt_user_data loader_data, const char *filename, lt_dladvise advise); static int vm_close (lt_user_data loader_data, lt_module module); @@ -56,6 +57,7 @@ const char *symbolname); static lt_dlinterface_id iface_id = 0; +static lt_dlvtable *vtable = 0; /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) @@ -63,8 +65,6 @@ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); @@ -77,6 +77,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_APPEND; } @@ -97,6 +98,15 @@ #include <windows.h> +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + /* A function called through the vtable to open a module with this loader. Returns an opaque representation of the newly opened module for processing with this loader's other vtable functions. */ Index: libltdl/loaders/preopen.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/preopen.c,v retrieving revision 1.16 diff -u -r1.16 preopen.c --- libltdl/loaders/preopen.c 30 Aug 2007 18:39:10 -0000 1.16 +++ libltdl/loaders/preopen.c 3 Mar 2008 21:41:04 -0000 @@ -1,7 +1,7 @@ /* loader-preopen.c -- emulate dynamic linking using preloaded_symbols Copyright (C) 1998, 1999, 2000, 2004, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Thomas Tanner, 1998 NOTE: The canonical source of this file is maintained with the @@ -53,14 +53,14 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); @@ -132,6 +132,7 @@ static int vl_exit (lt_user_data LT__UNUSED loader_data) { + vtable = NULL; free_symlists (); return 0; } Index: libltdl/loaders/shl_load.c =================================================================== RCS file: /cvsroot/libtool/libtool/libltdl/loaders/shl_load.c,v retrieving revision 1.10 diff -u -r1.10 shl_load.c --- libltdl/loaders/shl_load.c 8 May 2007 14:38:50 -0000 1.10 +++ libltdl/loaders/shl_load.c 3 Mar 2008 21:41:04 -0000 @@ -1,7 +1,7 @@ /* loader-shl_load.c -- dynamic linking with shl_load (HP-UX) Copyright (C) 1998, 1999, 2000, 2004, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008 Free Software Foundation, Inc. Written by Thomas Tanner, 1998 NOTE: The canonical source of this file is maintained with the @@ -45,20 +45,21 @@ /* Boilerplate code to set up the vtable for hooking this loader into libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); static lt_module vm_open (lt_user_data loader_data, const char *filename, lt_dladvise advise); static int vm_close (lt_user_data loader_data, lt_module module); static void * vm_sym (lt_user_data loader_data, lt_module module, const char *symbolname); +static lt_dlvtable *vtable = 0; + /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlvtable *vtable = 0; - if (!vtable) { vtable = lt__zalloc (sizeof *vtable); @@ -70,6 +71,7 @@ vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_APPEND; } @@ -133,6 +135,15 @@ #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data LT__UNUSED loader_data) +{ + vtable = NULL; + return 0; +} + /* A function called through the vtable to open a module with this loader. Returns an opaque representation of the newly opened module for processing with this loader's other vtable functions. */ Index: tests/lt_dlexit.at =================================================================== RCS file: /cvsroot/libtool/libtool/tests/lt_dlexit.at,v retrieving revision 1.10 diff -u -r1.10 lt_dlexit.at --- tests/lt_dlexit.at 1 Mar 2008 22:43:04 -0000 1.10 +++ tests/lt_dlexit.at 3 Mar 2008 21:41:04 -0000 @@ -32,6 +32,7 @@ # Test for # http://lists.gnu.org/archive/html/bug-libtool/2007-01/msg00014.html +# http://lists.gnu.org/archive/html/bug-libtool/2008-03/msg00013.html AT_DATA([main.c], [[#include <ltdl.h> @@ -80,6 +81,14 @@ fprintf (stderr, "error during initialization: %s\n", lt_dlerror()); return 1; } + if (lt_dlexit() != 0) { + fprintf (stderr, "error during first lt_dlexit: %s\n", lt_dlerror()); + return 1; + } + if (lt_dlinit() != 0) { + fprintf (stderr, "error during second initialization: %s\n", lt_dlerror()); + return 1; + } if (!(b1 = xdlopen ("modb1.la"))) return 1; if (xdlsymtest (b1, "fb1", "vb1")) return 1; /* do not lt_dlclose here on purpose. */