]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
* libltdl/ltdl.c: major rewrite to avoid almost all fixed-size
authorAlexandre Oliva <oliva@dcc.unicamp.br>
Thu, 21 Jan 1999 04:27:26 +0000 (04:27 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Thu, 21 Jan 1999 04:27:26 +0000 (04:27 +0000)
buffers; only `tmp' in lt_dlopen remained.  But the code got ugly
:-(

ChangeLog
libltdl/ltdl.c

index 238ca31494fc03d5f84a9446345c29f461f0fdbe..0063b3bf671d03be43899647f95fc5444b799deb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 1999-01-21  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
+       * libltdl/ltdl.c: major rewrite to avoid almost all fixed-size
+       buffers; only `tmp' in lt_dlopen remained.  But the code got ugly
+       :-(
+
        * ltconfig.in (linux-gnu*, finish_cmds): remove erroneous backslash
 
        * demo/configure.in: set DLPREOPEN to -dlopen if we don't have
index a193979448edde83059a1d659afb7bb2bbe3813e..c06650da799656371707f6b41a243ae8f8ad6959 100644 (file)
@@ -59,10 +59,6 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 # endif
 #endif
 
-#ifndef LTDL_SEARCHPATH_MAX
-#define LTDL_SEARCHPATH_MAX 4096
-#endif
-
 #undef LTDL_READTEXT_MODE
 /* fopen() mode flags for reading a text file */
 #ifdef _WIN32
@@ -73,7 +69,7 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 #undef LTDL_SYMBOL_LENGTH
 /* This is the maximum symbol size that won't require malloc/free */
-#define LTDL_SYMBOL_LENGTH     256
+#define LTDL_SYMBOL_LENGTH     128
 
 #undef LTDL_SYMBOL_OVERHEAD
 /* This accounts for the _LTX_ separator and the string terminator */
@@ -662,7 +658,8 @@ presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit,
 #undef LTDL_TYPE_TOP
 #define LTDL_TYPE_TOP &presym
 
-static char usr_search_path[LTDL_SEARCHPATH_MAX];
+static char *usr_search_path;
+static int usr_search_path_size = 0;
 static lt_dlhandle handles = 0;
 static int initialized = 0;
 
@@ -681,7 +678,9 @@ lt_dlinit ()
                return 0;
        }
        handles = 0;
-       usr_search_path[0] = '\0'; /* empty search path */
+       if (usr_search_path)
+               free(usr_search_path);
+       usr_search_path = 0; /* empty search path */
 
        while (*type) {
                if ((*type)->mod_init())
@@ -756,22 +755,6 @@ lt_dlexit ()
        return errors;
 }
 
-static int /* not all compilers support void */
-trim (dest, s)
-       char *dest;
-       const char *s;
-{
-       char *i = strrchr(s, '\'');
-       int len = strlen(s);
-
-       if (len > 3 && s[0] == '\'') {
-               strncpy(dest, &s[1], (i - s) - 1);
-               dest[len-3] = '\0';
-       } else
-               *dest = '\0';
-       return 0;
-}
-
 static int
 tryall_dlopen (handle, filename)
        lt_dlhandle *handle;
@@ -816,116 +799,140 @@ find_module (handle, dir, dlname, old_name)
        const char *dlname;
        const char *old_name;
 {
-       char    filename[LTDL_FILENAME_MAX];
-
        /* search for old library first; if it was dlpreopened, we
            want the preopened version of it, even if a dlopenable
            module is available */
-       if (*old_name && tryall_dlopen(handle, old_name) == 0)
+       if (old_name && tryall_dlopen(handle, old_name) == 0)
                return 0;
 
        /* search a module */
-       if (*dlname) {
-               /* hmm, maybe it was moved to another directory */
-               if (strlen(dir)+1+strlen(dlname) < LTDL_FILENAME_MAX) {
-                       strcpy(filename, dir);
-                       strcat(filename, "/");
-                       strcat(filename, dlname);
-                       if (tryall_dlopen(handle, filename) == 0)
-                               return 0;
+       if (dlname) {
+               char *filename = malloc(strlen(dir)+1+strlen(dlname)+1);
+
+               if (!filename) {
+                       last_error = memory_error;
+                       return 1;
+               }
+               strcpy(filename, dir);
+               strcat(filename, "/");
+               strcat(filename, dlname);
+               if (tryall_dlopen(handle, filename) == 0) {
+                       free(filename);
+                       return 0;
                }
+               free(filename);
        }
        last_error = file_not_found_error;
        return 1;
 }
 
+#undef LTDL_CHECK_SIZE
+#define LTDL_CHECK_SIZE(buf_, size_, need_, ret) do {                  \
+        char **pbuf = &buf_; int *psize = &size_, need = need_;                \
+       if (need > *psize) {                                            \
+               if (*pbuf)                                              \
+                       free(*pbuf);                                    \
+               *pbuf = malloc(need);                                   \
+               if (!*pbuf) {                                           \
+                       last_error = memory_error;                      \
+                       return ret;                                     \
+               }                                                       \
+       }                                                               \
+} while(0)                                                              
+                       
 static int
 find_library (handle, basename, search_path)
        lt_dlhandle *handle;
        const char *basename;
        const char *search_path;
 {
-       char    filename[LTDL_FILENAME_MAX];
+       char    *filename = 0;
+       int size = 0;
        const char *cur, *next;
+       int baselen;
        
        if (!search_path || !strlen(search_path)) {
                last_error = file_not_found_error;
                return 1;
        }
        cur = search_path;
+       baselen = strlen(basename);
        while (cur) {
+               int lendir;
                next = strchr(cur, ':');
-               if (next) {
-                       if (next - cur + 1 >= LTDL_FILENAME_MAX) {
-                               last_error = buffer_overflow_error;
-                               return 1;
-                       }
-                       strncpy(filename, cur, next - cur);
-                       filename[next - cur] = '\0';
+               if (next)
+                       lendir = next-cur;
+               else
+                       lendir = strlen(cur);
+               if (lendir == 0)
+                       continue;
+               LTDL_CHECK_SIZE(filename, size, \
+                               lendir + 1 + baselen + 1, 1);
+               strncpy(filename, cur, lendir);
+               if (next)
                        cur = next+1;
-               } else {
-                       if (strlen(cur)+1 >= LTDL_FILENAME_MAX) {
-                               last_error = buffer_overflow_error;
-                               return 1;
-                       }
-                       strcpy(filename, cur);
+               else
                        cur = 0;
-               }
-               if (!*filename)
-                       continue;
-               strcat(filename, "/");
-               if (strlen(filename)+strlen(basename) < LTDL_FILENAME_MAX) {
-                       strcat(filename, basename);
-                       if (tryall_dlopen(handle, filename) == 0)
-                               return 0;
+               filename[lendir] = '/';
+               strncpy(filename+lendir+1, basename, baselen+1);
+               if (tryall_dlopen(handle, filename) == 0) {
+                       free(filename);
+                       return 0;
                }
        }
+       free(filename);
        last_error = file_not_found_error;
        return 1;
 }
 
 static FILE *
-find_file (basename, search_path)
+find_file (basename, search_path, pdir)
        const char *basename;
        const char *search_path;
+       const char **pdir;
 {
-       char    filename[LTDL_FILENAME_MAX];
+       char    *filename = 0;
+       int size = 0;
        const char *cur, *next;
        FILE    *file;
-       
+       int baselen;
+       int overhead;
+
        if (!search_path || !strlen(search_path)) {
                last_error = file_not_found_error;
                return 0;
        }
        cur = search_path;
+       baselen = strlen(basename);
+       overhead = strlen(LTDL_OBJDIR)+1;
+       if (baselen > overhead)
+               overhead = baselen;
        while (cur) {
+               int lendir;
                next = strchr(cur, ':');
-               if (next) {
-                       if (next - cur + 1 >= LTDL_FILENAME_MAX) {
-                               last_error = buffer_overflow_error;
-                               return 0;
-                       }
-                       strncpy(filename, cur, next - cur);
-                       filename[next - cur] = '\0';
+               if (next)
+                       lendir = next-cur;
+               else
+                       lendir = strlen(cur);
+               if (lendir == 0)
+                       continue;
+               LTDL_CHECK_SIZE(filename, size, \
+                               lendir + 1 + overhead + 1, 0);
+               strncpy(filename, cur, lendir);
+               if (next)
                        cur = next+1;
-               } else {
-                       if (strlen(cur)+1 >= LTDL_FILENAME_MAX) {
-                               last_error = buffer_overflow_error;
-                               return 0;
-                       }
-                       strcpy(filename, cur);
+               else
                        cur = 0;
-               }
-               if (!*filename)
-                       continue;
-               strcat(filename, "/");
-               if (strlen(filename)+strlen(basename) < LTDL_FILENAME_MAX) {
-                       strcat(filename, basename);
-                       file = fopen(filename, LTDL_READTEXT_MODE);
-                       if (file)
-                               return file;
+               filename[lendir] = '/';
+               strncpy(filename+lendir+1, basename, baselen+1);
+               file = fopen(filename, LTDL_READTEXT_MODE);
+               if (file) {
+                       filename[lendir+1] = '\0';
+                       *pdir = filename;
+                       return file;
                }
        }
+       free(filename);
        last_error = file_not_found_error;
        return 0;
 }
@@ -949,38 +956,53 @@ unload_deplibs(handle)
        return 0;
 }
 
+#undef LTDL_TRIM
+#define LTDL_TRIM(dest_, s_) do {                      \
+       char **dest = &(dest_);                         \
+       char *s = (s_);                                 \
+       int len = strlen(s);                            \
+                                                       \
+       if (*dest)                                      \
+               free(*dest);                            \
+       *dest = 0;                                      \
+                                                       \
+       if (len > 3 && s[0] == '\''                     \
+           && s[len-1] == '\n' && s[len-2] == '\'') {  \
+               *dest = malloc(len-2);                  \
+               if (!*dest)                             \
+                       goto trim_raise_memory_error;   \
+               strncpy(*dest, &s[1], len - 3);         \
+               (*dest)[len-3] = '\0';                  \
+       }                                               \
+} while(0)                                              
+
 lt_dlhandle
 lt_dlopen (filename)
        const char *filename;
 {
-       lt_dlhandle handle;
-       char    dir[LTDL_FILENAME_MAX];
-       const char *basename, *ext, *search_path;
-#ifdef LTDL_SHLIBPATH_VAR
-       const char *sys_search_path;
-#endif
+       lt_dlhandle handle = 0;
+       char *dir = 0;
+       const char *basename, *ext;
        const char *saved_error = last_error;
        
        basename = strrchr(filename, '/');
-       if (basename)
+       if (basename) {
                basename++;
-       else
+               dir = malloc(basename - filename + strlen(LTDL_OBJDIR) + 1);
+               if (!dir) {
+                       last_error = memory_error;
+                       return 0;
+               }
+               strncpy(dir, filename, basename-filename);
+               dir[basename-filename] = '\0';
+       } else
                basename = filename;
-       if (basename - filename >= LTDL_FILENAME_MAX) {
-               last_error = buffer_overflow_error;
-               return 0;
-       }
-       strncpy(dir, filename, basename - filename);
-       dir[basename - filename] = '\0';
-       search_path = getenv("LTDL_LIBRARY_PATH"); /* get the search path */
-#ifdef LTDL_SHLIBPATH_VAR
-       sys_search_path = getenv(LTDL_SHLIBPATH_VAR);
-#endif
+
        /* check whether we open a libtool module (.la extension) */
        ext = strrchr(basename, '.');
        if (ext && strcmp(ext, ".la") == 0) {
-               char    dlname[LTDL_FILENAME_MAX], old_name[LTDL_FILENAME_MAX];
-               char    libdir[LTDL_FILENAME_MAX], deplibs[LTDL_FILENAME_MAX];
+               char    *dlname = 0, *old_name = 0;
+               char    *libdir = 0, *deplibs = 0;
                char    tmp[LTDL_FILENAME_MAX];
                char    *name;
                FILE    *file;
@@ -990,10 +1012,8 @@ lt_dlopen (filename)
                   of libtool */
                int     installed=1; 
 
-               dlname[0] = old_name[0] = libdir[0] = deplibs[0] = '\0';
-
                /* extract the module name from the file name */
-               if (strlen(basename) >= LTDL_FILENAME_MAX) {
+               if (strlen(basename) >= sizeof(tmp)) {
                        last_error = buffer_overflow_error;
                        return 0;
                }
@@ -1009,96 +1029,119 @@ lt_dlopen (filename)
                        return 0;
                }
                file = fopen(filename, LTDL_READTEXT_MODE);
-               if (!file && !*dir) {
+               if (!file && !dir) {
                        /* try other directories */
-                       file = find_file(basename, usr_search_path);
+                       file = find_file(basename, usr_search_path, &dir);
                        if (!file)
-                               file = find_file(basename, search_path);
+                               file = find_file(basename,
+                                                getenv("LTDL_LIBRARY_PATH"),
+                                                &dir);
 #ifdef LTDL_SHLIBPATH_VAR
                        if (!file)
-                               file = find_file(basename, sys_search_path);
+                               file = find_file(basename,
+                                                getenv(LTDL_SHLIBPATH_VAR),
+                                                &dir);
 #endif
                }
                if (!file) {
+               clean_up_name:
                        free(name);
-                       return 0;
+                       goto clean_up_dir;
                }
                while (!feof(file)) {
-                       if (!fgets(tmp, LTDL_FILENAME_MAX, file))
+                       if (!fgets(tmp, sizeof(tmp), file))
                                break;
+                       if (tmp[0] == '\n' || tmp[0] == '#')
+                               ;
+                       else
                        if (strncmp(tmp, "dlname=", 7) == 0)
-                               trim(dlname, &tmp[7]);
+                               LTDL_TRIM(dlname, &tmp[7]);
                        else
                        if (strncmp(tmp, "old_library=", 12) == 0)
-                               trim(old_name, &tmp[12]);
+                               LTDL_TRIM(old_name, &tmp[12]);
                        else
                        if (strncmp(tmp, "libdir=", 7) == 0)
-                               trim(libdir, &tmp[7]);
+                               LTDL_TRIM(libdir, &tmp[7]);
                        else
                        if (strncmp(tmp, "dl_dependency_libs=", 20) == 0)
-                               trim(deplibs, &tmp[20]);
+                               LTDL_TRIM(deplibs, &tmp[20]);
                        else
                        if (strcmp(tmp, "installed=yes\n") == 0)
                                installed = 1;
                        else
                        if (strcmp(tmp, "installed=no\n") == 0)
                                installed = 0;
+                       else
+                       if (0) {
+                       trim_raise_memory_error:
+                               fclose(file);
+                               goto handle_raise_memory_error;
+                       }
                }
                fclose(file);
                
                handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
                if (!handle) {
+               handle_raise_memory_error:
                        last_error = memory_error;
-                       free(name);
-                       return 0;
+                       goto clean_up_vars;
                }
-               if (load_deplibs(handle, deplibs)) {
+               if (deplibs && load_deplibs(handle, deplibs)) {
+               clean_up_handle:
                        free(handle);
-                       free(name);
-                       return 0;
+                       handle = 0;
+                       goto clean_up_vars;
                }
                if (installed) {
                        if (find_module(&handle, libdir, dlname, old_name)) {
+                       clean_up_deplibs:
                                unload_deplibs(handle);
-                               free(handle);
-                               free(name);
-                               return 0;
+                               goto clean_up_handle;
                        }
                } else {
-                       if (strlen(dir) + strlen(LTDL_OBJDIR)
-                           >= LTDL_FILENAME_MAX) {
-                               last_error = buffer_overflow_error;
-                               unload_deplibs(handle);
-                               free(handle);
-                               free(name);
-                               return 0;
-                       }
-                       strcat(dir, LTDL_OBJDIR);
-                       if (find_module(&handle, dir, dlname, old_name)) {
-                               unload_deplibs(handle);
-                               free(handle);
-                               free(name);
-                               return 0;
-                       }
+                       /* We dir is non-NULL, it has enough space for
+                          LTDL_OBJDIR: it was reserved in the
+                          beginning of the function or within
+                          find_file */
+                       if (dir)
+                               strcat(dir, LTDL_OBJDIR);
+                       if (find_module(&handle,
+                                       dir ? dir : LTDL_OBJDIR,
+                                       dlname, old_name))
+                               goto clean_up_deplibs;
                }
                handle->name = name;
+       clean_up_vars:
+               if (dlname)
+                       free(dlname);
+               if (old_name)
+                       free(old_name);
+               if (libdir)
+                       free(libdir);
+               if (deplibs)
+                       free(deplibs);
+               if (!handle)
+                       goto clean_up_name;
        } else {
                /* not a libtool module */
                handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
                if (!handle) {
                        last_error = memory_error;
-                       return 0;
+                       goto clean_up_dir;
                }
                if (tryall_dlopen(&handle, filename)
-                   && (*dir
+                   && (dir
                        || (find_library(&handle, basename, usr_search_path)
-                           && find_library(&handle, basename, search_path)
+                           && find_library(&handle, basename,
+                                           getenv("LTDL_LIBRARY_PATH"))
 #ifdef LTDL_SHLIBPATH_VAR
-                           && find_library(&handle, basename, sys_search_path)
+                           && find_library(&handle, basename,
+                                           getenv(LTDL_SHLIBPATH_VAR))
 #endif
                                ))) {
                        free(handle);
-                       return 0;
+                       handle = 0;
+                       goto clean_up_dir;
                }
                handle->name = 0;
        }
@@ -1106,6 +1149,9 @@ lt_dlopen (filename)
        handle->next = handles;
        handles = handle;
        last_error = saved_error;
+ clean_up_dir:
+       if (dir)
+               free(dir);
        return handle;
 }
 
@@ -1218,19 +1264,33 @@ lt_dladdsearchdir (search_dir)
        const char *search_dir;
 {
        if (!search_dir) {
-               usr_search_path[0] = '\0'; /* reset the search path */
+               if (usr_search_path)
+                       free(usr_search_path);
+               usr_search_path = 0; /* reset the search path */
                return 0;
        }
        if (!strlen(search_dir))
                return 0;
-       if (strlen(usr_search_path) + strlen(search_dir) + 1
-           >= LTDL_SEARCHPATH_MAX) {
-               last_error = buffer_overflow_error;
-               return 1;
-       }
-       if (usr_search_path[0] != '\0')
+       if (!usr_search_path) {
+               usr_search_path_size = strlen(search_dir)+1;
+               usr_search_path = malloc(usr_search_path_size);
+               if (!usr_search_path) {
+                       last_error = memory_error;
+                       return 1;
+               }
+               strcpy(usr_search_path, search_dir);
+       } else {
+               int new_size = usr_search_path_size + strlen(search_dir) + 1;
+               char *new_search_path = realloc(usr_search_path, new_size);
+               if (!new_search_path) {
+                       last_error = memory_error;
+                       return 1;
+               }
+               usr_search_path = new_search_path;
+               usr_search_path_size = new_size;
                strcat(usr_search_path, ":");
-       strcat(usr_search_path, search_dir);
+               strcat(usr_search_path, search_dir);
+       }
        return 0;
 }
 
@@ -1238,17 +1298,17 @@ int
 lt_dlsetsearchpath (search_path)
        const char *search_path;
 {
-       if (!search_path) {
-               usr_search_path[0] = '\0'; /* reset the search path */
+       if (usr_search_path)
+               free(usr_search_path);
+       usr_search_path = 0; /* reset the search path */
+       if (!search_path || !strlen(search_path)) {
                return 0;
        }
-       if (!strlen(search_path))
-               return 0;
-       if (strlen(search_path) >= LTDL_SEARCHPATH_MAX) {
-               last_error = buffer_overflow_error;
+       usr_search_path = strdup(search_path);
+       if (usr_search_path)
+               usr_search_path_size = strlen(usr_search_path)+1;
+       else
                return 1;
-       }
-       strcpy(usr_search_path, search_path);
        return 0;
 }