mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 13:11:22 +02:00
Plug memory leaks introduced by dynamic-search-path changes.
From Teodor Sigaev.
This commit is contained in:
parent
38633cf891
commit
3f8a50c013
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.51 2001/09/16 16:11:11 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.52 2001/10/04 19:13:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* List of dynamically loaded files.
|
||||
* List of dynamically loaded files (kept in malloc'd memory).
|
||||
*/
|
||||
|
||||
typedef struct df_files
|
||||
@ -71,25 +71,25 @@ load_external_function(char *filename, char *funcname,
|
||||
char *fullname;
|
||||
|
||||
fullname = expand_dynamic_library_name(filename);
|
||||
if (fullname)
|
||||
filename = fullname;
|
||||
if (!fullname)
|
||||
fullname = pstrdup(filename);
|
||||
/* at this point fullname is always freshly palloc'd */
|
||||
|
||||
/*
|
||||
* Scan the list of loaded FILES to see if the file has been loaded.
|
||||
*/
|
||||
for (file_scanner = file_list;
|
||||
file_scanner != (DynamicFileList *) NULL &&
|
||||
strcmp(filename, file_scanner->filename) != 0;
|
||||
strcmp(fullname, file_scanner->filename) != 0;
|
||||
file_scanner = file_scanner->next)
|
||||
;
|
||||
if (file_scanner == (DynamicFileList *) NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check for same files - different paths (ie, symlink or link)
|
||||
*/
|
||||
if (stat(filename, &stat_buf) == -1)
|
||||
elog(ERROR, "stat failed on file '%s': %m", filename);
|
||||
if (stat(fullname, &stat_buf) == -1)
|
||||
elog(ERROR, "stat failed on file '%s': %m", fullname);
|
||||
|
||||
for (file_scanner = file_list;
|
||||
file_scanner != (DynamicFileList *) NULL &&
|
||||
@ -100,27 +100,26 @@ load_external_function(char *filename, char *funcname,
|
||||
|
||||
if (file_scanner == (DynamicFileList *) NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* File not loaded yet.
|
||||
*/
|
||||
file_scanner = (DynamicFileList *)
|
||||
malloc(sizeof(DynamicFileList) + strlen(filename));
|
||||
malloc(sizeof(DynamicFileList) + strlen(fullname));
|
||||
if (file_scanner == NULL)
|
||||
elog(ERROR, "Out of memory in load_external_function");
|
||||
|
||||
MemSet((char *) file_scanner, 0, sizeof(DynamicFileList));
|
||||
strcpy(file_scanner->filename, filename);
|
||||
strcpy(file_scanner->filename, fullname);
|
||||
file_scanner->device = stat_buf.st_dev;
|
||||
file_scanner->inode = stat_buf.st_ino;
|
||||
file_scanner->next = (DynamicFileList *) NULL;
|
||||
|
||||
file_scanner->handle = pg_dlopen(filename);
|
||||
file_scanner->handle = pg_dlopen(fullname);
|
||||
if (file_scanner->handle == (void *) NULL)
|
||||
{
|
||||
load_error = (char *) pg_dlerror();
|
||||
free((char *) file_scanner);
|
||||
elog(ERROR, "Load of file %s failed: %s", filename, load_error);
|
||||
elog(ERROR, "Load of file %s failed: %s", fullname, load_error);
|
||||
}
|
||||
|
||||
/* OK to link it into list */
|
||||
@ -135,13 +134,17 @@ load_external_function(char *filename, char *funcname,
|
||||
* If funcname is NULL, we only wanted to load the file.
|
||||
*/
|
||||
if (funcname == (char *) NULL)
|
||||
{
|
||||
pfree(fullname);
|
||||
return (PGFunction) NULL;
|
||||
}
|
||||
|
||||
retval = pg_dlsym(file_scanner->handle, funcname);
|
||||
|
||||
if (retval == (PGFunction) NULL && signalNotFound)
|
||||
elog(ERROR, "Can't find function %s in file %s", funcname, filename);
|
||||
elog(ERROR, "Can't find function %s in file %s", funcname, fullname);
|
||||
|
||||
pfree(fullname);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -159,16 +162,17 @@ load_file(char *filename)
|
||||
char *fullname;
|
||||
|
||||
fullname = expand_dynamic_library_name(filename);
|
||||
if (fullname)
|
||||
filename = fullname;
|
||||
if (!fullname)
|
||||
fullname = pstrdup(filename);
|
||||
/* at this point fullname is always freshly palloc'd */
|
||||
|
||||
/*
|
||||
* We need to do stat() in order to determine whether this is the same
|
||||
* file as a previously loaded file; it's also handy so as to give a
|
||||
* good error message if bogus file name given.
|
||||
*/
|
||||
if (stat(filename, &stat_buf) == -1)
|
||||
elog(ERROR, "LOAD: could not open file '%s': %m", filename);
|
||||
if (stat(fullname, &stat_buf) == -1)
|
||||
elog(ERROR, "LOAD: could not open file '%s': %m", fullname);
|
||||
|
||||
if (file_list != (DynamicFileList *) NULL)
|
||||
{
|
||||
@ -197,7 +201,9 @@ load_file(char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
load_external_function(filename, (char *) NULL, false);
|
||||
load_external_function(fullname, (char *) NULL, false);
|
||||
|
||||
pfree(fullname);
|
||||
}
|
||||
|
||||
|
||||
@ -235,6 +241,8 @@ file_exists(const char *name)
|
||||
* find_in_dynamic_libpath below); if that works, return the fully
|
||||
* expanded file name. If the previous failed, append DLSUFFIX and
|
||||
* try again. If all fails, return NULL.
|
||||
*
|
||||
* A non-NULL result will always be freshly palloc'd.
|
||||
*/
|
||||
static char *
|
||||
expand_dynamic_library_name(const char *name)
|
||||
@ -258,6 +266,7 @@ expand_dynamic_library_name(const char *name)
|
||||
full = substitute_libpath_macro(name);
|
||||
if (file_exists(full))
|
||||
return full;
|
||||
pfree(full);
|
||||
}
|
||||
|
||||
new = palloc(strlen(name)+ strlen(DLSUFFIX) + 1);
|
||||
@ -274,15 +283,20 @@ expand_dynamic_library_name(const char *name)
|
||||
else
|
||||
{
|
||||
full = substitute_libpath_macro(new);
|
||||
pfree(new);
|
||||
if (file_exists(full))
|
||||
return full;
|
||||
pfree(full);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Substitute for any macros appearing in the given string.
|
||||
* Result is always freshly palloc'd.
|
||||
*/
|
||||
static char *
|
||||
substitute_libpath_macro(const char * name)
|
||||
{
|
||||
@ -302,7 +316,7 @@ substitute_libpath_macro(const char * name)
|
||||
elog(ERROR, "invalid macro name in dynamic library path");
|
||||
|
||||
if (name[macroname_len] == '\0')
|
||||
return replacement;
|
||||
return pstrdup(replacement);
|
||||
else
|
||||
{
|
||||
char * new;
|
||||
@ -319,15 +333,14 @@ substitute_libpath_macro(const char * name)
|
||||
|
||||
/*
|
||||
* Search for a file called 'basename' in the colon-separated search
|
||||
* path 'path'. If the file is found, the full file name is returned
|
||||
* in palloced memory. The the file is not found, return NULL.
|
||||
* path Dynamic_library_path. If the file is found, the full file name
|
||||
* is returned in freshly palloc'd memory. If the file is not found,
|
||||
* return NULL.
|
||||
*/
|
||||
static char *
|
||||
find_in_dynamic_libpath(const char * basename)
|
||||
{
|
||||
const char *p;
|
||||
char *full;
|
||||
size_t len;
|
||||
size_t baselen;
|
||||
|
||||
AssertArg(basename != NULL);
|
||||
@ -340,9 +353,12 @@ find_in_dynamic_libpath(const char * basename)
|
||||
|
||||
baselen = strlen(basename);
|
||||
|
||||
do {
|
||||
for (;;)
|
||||
{
|
||||
size_t len;
|
||||
char * piece;
|
||||
const char * mangled;
|
||||
char * mangled;
|
||||
char *full;
|
||||
|
||||
len = strcspn(p, ":");
|
||||
|
||||
@ -354,6 +370,7 @@ find_in_dynamic_libpath(const char * basename)
|
||||
piece[len] = '\0';
|
||||
|
||||
mangled = substitute_libpath_macro(piece);
|
||||
pfree(piece);
|
||||
|
||||
/* only absolute paths */
|
||||
if (mangled[0] != '/')
|
||||
@ -361,6 +378,7 @@ find_in_dynamic_libpath(const char * basename)
|
||||
|
||||
full = palloc(strlen(mangled) + 1 + baselen + 1);
|
||||
sprintf(full, "%s/%s", mangled, basename);
|
||||
pfree(mangled);
|
||||
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "find_in_dynamic_libpath: trying %s", full);
|
||||
@ -368,13 +386,13 @@ find_in_dynamic_libpath(const char * basename)
|
||||
if (file_exists(full))
|
||||
return full;
|
||||
|
||||
pfree(piece);
|
||||
pfree(full);
|
||||
|
||||
if (p[len] == '\0')
|
||||
break;
|
||||
else
|
||||
p += len + 1;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user