~ari-tczew/ubuntu/dapper/fetchmail/fix-CVE-2008-2711

« back to all changes in this revision

Viewing changes to intl/relocatable.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-02-07 12:12:13 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060207121213-onurwfrzdlzlzxnt
Tags: 6.3.2-2ubuntu1
* Resynchronise with Debian. This brings the new upstream version to dapper
  since upstream support for 6.2 was dropped.
* Drop debian/patches/CVE-2005-4348.dpatch, upstream now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Provide relocatable packages.
2
 
   Copyright (C) 2003 Free Software Foundation, Inc.
3
 
   Written by Bruno Haible <bruno@clisp.org>, 2003.
4
 
 
5
 
   This program is free software; you can redistribute it and/or modify it
6
 
   under the terms of the GNU Library General Public License as published
7
 
   by the Free Software Foundation; either version 2, or (at your option)
8
 
   any later version.
9
 
 
10
 
   This program is distributed in the hope that it will be useful,
11
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
   Library General Public License for more details.
14
 
 
15
 
   You should have received a copy of the GNU Library General Public
16
 
   License along with this program; if not, write to the Free Software
17
 
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18
 
   USA.  */
19
 
 
20
 
 
21
 
/* Tell glibc's <stdio.h> to provide a prototype for getline().
22
 
   This must come before <config.h> because <config.h> may include
23
 
   <features.h>, and once <features.h> has been included, it's too late.  */
24
 
#ifndef _GNU_SOURCE
25
 
# define _GNU_SOURCE    1
26
 
#endif
27
 
 
28
 
#ifdef HAVE_CONFIG_H
29
 
# include "config.h"
30
 
#endif
31
 
 
32
 
/* Specification.  */
33
 
#include "relocatable.h"
34
 
 
35
 
#if ENABLE_RELOCATABLE
36
 
 
37
 
#include <stddef.h>
38
 
#include <stdio.h>
39
 
#include <stdlib.h>
40
 
#include <string.h>
41
 
 
42
 
#ifdef NO_XMALLOC
43
 
# define xmalloc malloc
44
 
#else
45
 
# include "xalloc.h"
46
 
#endif
47
 
 
48
 
#if defined _WIN32 || defined __WIN32__
49
 
# define WIN32_LEAN_AND_MEAN
50
 
# include <windows.h>
51
 
#endif
52
 
 
53
 
#if DEPENDS_ON_LIBCHARSET
54
 
# include <libcharset.h>
55
 
#endif
56
 
#if DEPENDS_ON_LIBICONV && HAVE_ICONV
57
 
# include <iconv.h>
58
 
#endif
59
 
#if DEPENDS_ON_LIBINTL && ENABLE_NLS
60
 
# include <libintl.h>
61
 
#endif
62
 
 
63
 
/* Faked cheap 'bool'.  */
64
 
#undef bool
65
 
#undef false
66
 
#undef true
67
 
#define bool int
68
 
#define false 0
69
 
#define true 1
70
 
 
71
 
/* Pathname support.
72
 
   ISSLASH(C)           tests whether C is a directory separator character.
73
 
   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
74
 
 */
75
 
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
76
 
  /* Win32, OS/2, DOS */
77
 
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
78
 
# define HAS_DEVICE(P) \
79
 
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
80
 
     && (P)[1] == ':')
81
 
# define IS_PATH_WITH_DIR(P) \
82
 
    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
83
 
# define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
84
 
#else
85
 
  /* Unix */
86
 
# define ISSLASH(C) ((C) == '/')
87
 
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
88
 
# define FILESYSTEM_PREFIX_LEN(P) 0
89
 
#endif
90
 
 
91
 
/* Original installation prefix.  */
92
 
static char *orig_prefix;
93
 
static size_t orig_prefix_len;
94
 
/* Current installation prefix.  */
95
 
static char *curr_prefix;
96
 
static size_t curr_prefix_len;
97
 
/* These prefixes do not end in a slash.  Anything that will be concatenated
98
 
   to them must start with a slash.  */
99
 
 
100
 
/* Sets the original and the current installation prefix of this module.
101
 
   Relocation simply replaces a pathname starting with the original prefix
102
 
   by the corresponding pathname with the current prefix instead.  Both
103
 
   prefixes should be directory names without trailing slash (i.e. use ""
104
 
   instead of "/").  */
105
 
static void
106
 
set_this_relocation_prefix (const char *orig_prefix_arg,
107
 
                            const char *curr_prefix_arg)
108
 
{
109
 
  if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
110
 
      /* Optimization: if orig_prefix and curr_prefix are equal, the
111
 
         relocation is a nop.  */
112
 
      && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
113
 
    {
114
 
      /* Duplicate the argument strings.  */
115
 
      char *memory;
116
 
 
117
 
      orig_prefix_len = strlen (orig_prefix_arg);
118
 
      curr_prefix_len = strlen (curr_prefix_arg);
119
 
      memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
120
 
#ifdef NO_XMALLOC
121
 
      if (memory != NULL)
122
 
#endif
123
 
        {
124
 
          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
125
 
          orig_prefix = memory;
126
 
          memory += orig_prefix_len + 1;
127
 
          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
128
 
          curr_prefix = memory;
129
 
          return;
130
 
        }
131
 
    }
132
 
  orig_prefix = NULL;
133
 
  curr_prefix = NULL;
134
 
  /* Don't worry about wasted memory here - this function is usually only
135
 
     called once.  */
136
 
}
137
 
 
138
 
/* Sets the original and the current installation prefix of the package.
139
 
   Relocation simply replaces a pathname starting with the original prefix
140
 
   by the corresponding pathname with the current prefix instead.  Both
141
 
   prefixes should be directory names without trailing slash (i.e. use ""
142
 
   instead of "/").  */
143
 
void
144
 
set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
145
 
{
146
 
  set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
147
 
 
148
 
  /* Now notify all dependent libraries.  */
149
 
#if DEPENDS_ON_LIBCHARSET
150
 
  libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
151
 
#endif
152
 
#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
153
 
  libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
154
 
#endif
155
 
#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
156
 
  libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
157
 
#endif
158
 
}
159
 
 
160
 
#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR)
161
 
 
162
 
/* Convenience function:
163
 
   Computes the current installation prefix, based on the original
164
 
   installation prefix, the original installation directory of a particular
165
 
   file, and the current pathname of this file.  Returns NULL upon failure.  */
166
 
#ifdef IN_LIBRARY
167
 
#define compute_curr_prefix local_compute_curr_prefix
168
 
static
169
 
#endif
170
 
const char *
171
 
compute_curr_prefix (const char *orig_installprefix,
172
 
                     const char *orig_installdir,
173
 
                     const char *curr_pathname)
174
 
{
175
 
  const char *curr_installdir;
176
 
  const char *rel_installdir;
177
 
 
178
 
  if (curr_pathname == NULL)
179
 
    return NULL;
180
 
 
181
 
  /* Determine the relative installation directory, relative to the prefix.
182
 
     This is simply the difference between orig_installprefix and
183
 
     orig_installdir.  */
184
 
  if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
185
 
      != 0)
186
 
    /* Shouldn't happen - nothing should be installed outside $(prefix).  */
187
 
    return NULL;
188
 
  rel_installdir = orig_installdir + strlen (orig_installprefix);
189
 
 
190
 
  /* Determine the current installation directory.  */
191
 
  {
192
 
    const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname);
193
 
    const char *p = curr_pathname + strlen (curr_pathname);
194
 
    char *q;
195
 
 
196
 
    while (p > p_base)
197
 
      {
198
 
        p--;
199
 
        if (ISSLASH (*p))
200
 
          break;
201
 
      }
202
 
 
203
 
    q = (char *) xmalloc (p - curr_pathname + 1);
204
 
#ifdef NO_XMALLOC
205
 
    if (q == NULL)
206
 
      return NULL;
207
 
#endif
208
 
    memcpy (q, curr_pathname, p - curr_pathname);
209
 
    q[p - curr_pathname] = '\0';
210
 
    curr_installdir = q;
211
 
  }
212
 
 
213
 
  /* Compute the current installation prefix by removing the trailing
214
 
     rel_installdir from it.  */
215
 
  {
216
 
    const char *rp = rel_installdir + strlen (rel_installdir);
217
 
    const char *cp = curr_installdir + strlen (curr_installdir);
218
 
    const char *cp_base =
219
 
      curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir);
220
 
 
221
 
    while (rp > rel_installdir && cp > cp_base)
222
 
      {
223
 
        bool same = false;
224
 
        const char *rpi = rp;
225
 
        const char *cpi = cp;
226
 
 
227
 
        while (rpi > rel_installdir && cpi > cp_base)
228
 
          {
229
 
            rpi--;
230
 
            cpi--;
231
 
            if (ISSLASH (*rpi) || ISSLASH (*cpi))
232
 
              {
233
 
                if (ISSLASH (*rpi) && ISSLASH (*cpi))
234
 
                  same = true;
235
 
                break;
236
 
              }
237
 
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
238
 
            /* Win32, OS/2, DOS - case insignificant filesystem */
239
 
            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
240
 
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
241
 
              break;
242
 
#else
243
 
            if (*rpi != *cpi)
244
 
              break;
245
 
#endif
246
 
          }
247
 
        if (!same)
248
 
          break;
249
 
        /* The last pathname component was the same.  opi and cpi now point
250
 
           to the slash before it.  */
251
 
        rp = rpi;
252
 
        cp = cpi;
253
 
      }
254
 
 
255
 
    if (rp > rel_installdir)
256
 
      /* Unexpected: The curr_installdir does not end with rel_installdir.  */
257
 
      return NULL;
258
 
 
259
 
    {
260
 
      size_t curr_prefix_len = cp - curr_installdir;
261
 
      char *curr_prefix;
262
 
 
263
 
      curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
264
 
#ifdef NO_XMALLOC
265
 
      if (curr_prefix == NULL)
266
 
        return NULL;
267
 
#endif
268
 
      memcpy (curr_prefix, curr_installdir, curr_prefix_len);
269
 
      curr_prefix[curr_prefix_len] = '\0';
270
 
 
271
 
      return curr_prefix;
272
 
    }
273
 
  }
274
 
}
275
 
 
276
 
#endif /* !IN_LIBRARY || PIC */
277
 
 
278
 
#if defined PIC && defined INSTALLDIR
279
 
 
280
 
/* Full pathname of shared library, or NULL.  */
281
 
static char *shared_library_fullname;
282
 
 
283
 
#if defined _WIN32 || defined __WIN32__
284
 
 
285
 
/* Determine the full pathname of the shared library when it is loaded.  */
286
 
 
287
 
BOOL WINAPI
288
 
DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
289
 
{
290
 
  (void) reserved;
291
 
 
292
 
  if (event == DLL_PROCESS_ATTACH)
293
 
    {
294
 
      /* The DLL is being loaded into an application's address range.  */
295
 
      static char location[MAX_PATH];
296
 
 
297
 
      if (!GetModuleFileName (module_handle, location, sizeof (location)))
298
 
        /* Shouldn't happen.  */
299
 
        return FALSE;
300
 
 
301
 
      if (!IS_PATH_WITH_DIR (location))
302
 
        /* Shouldn't happen.  */
303
 
        return FALSE;
304
 
 
305
 
      shared_library_fullname = strdup (location);
306
 
    }
307
 
 
308
 
  return TRUE;
309
 
}
310
 
 
311
 
#else /* Unix */
312
 
 
313
 
static void
314
 
find_shared_library_fullname ()
315
 
{
316
 
#if defined __linux__ && __GLIBC__ >= 2
317
 
  /* Linux has /proc/self/maps. glibc 2 has the getline() function.  */
318
 
  FILE *fp;
319
 
 
320
 
  /* Open the current process' maps file.  It describes one VMA per line.  */
321
 
  fp = fopen ("/proc/self/maps", "r");
322
 
  if (fp)
323
 
    {
324
 
      unsigned long address = (unsigned long) &find_shared_library_fullname;
325
 
      for (;;)
326
 
        {
327
 
          unsigned long start, end;
328
 
          int c;
329
 
 
330
 
          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
331
 
            break;
332
 
          if (address >= start && address <= end - 1)
333
 
            {
334
 
              /* Found it.  Now see if this line contains a filename.  */
335
 
              while (c = getc (fp), c != EOF && c != '\n' && c != '/')
336
 
                continue;
337
 
              if (c == '/')
338
 
                {
339
 
                  size_t size;
340
 
                  int len;
341
 
 
342
 
                  ungetc (c, fp);
343
 
                  shared_library_fullname = NULL; size = 0;
344
 
                  len = getline (&shared_library_fullname, &size, fp);
345
 
                  if (len >= 0)
346
 
                    {
347
 
                      /* Success: filled shared_library_fullname.  */
348
 
                      if (len > 0 && shared_library_fullname[len - 1] == '\n')
349
 
                        shared_library_fullname[len - 1] = '\0';
350
 
                    }
351
 
                }
352
 
              break;
353
 
            }
354
 
          while (c = getc (fp), c != EOF && c != '\n')
355
 
            continue;
356
 
        }
357
 
      fclose (fp);
358
 
    }
359
 
#endif
360
 
}
361
 
 
362
 
#endif /* WIN32 / Unix */
363
 
 
364
 
/* Return the full pathname of the current shared library.
365
 
   Return NULL if unknown.
366
 
   Guaranteed to work only on Linux and Woe32.  */
367
 
static char *
368
 
get_shared_library_fullname ()
369
 
{
370
 
#if !(defined _WIN32 || defined __WIN32__)
371
 
  static bool tried_find_shared_library_fullname;
372
 
  if (!tried_find_shared_library_fullname)
373
 
    {
374
 
      find_shared_library_fullname ();
375
 
      tried_find_shared_library_fullname = true;
376
 
    }
377
 
#endif
378
 
  return shared_library_fullname;
379
 
}
380
 
 
381
 
#endif /* PIC */
382
 
 
383
 
/* Returns the pathname, relocated according to the current installation
384
 
   directory.  */
385
 
const char *
386
 
relocate (const char *pathname)
387
 
{
388
 
#if defined PIC && defined INSTALLDIR
389
 
  static int initialized;
390
 
 
391
 
  /* Initialization code for a shared library.  */
392
 
  if (!initialized)
393
 
    {
394
 
      /* At this point, orig_prefix and curr_prefix likely have already been
395
 
         set through the main program's set_program_name_and_installdir
396
 
         function.  This is sufficient in the case that the library has
397
 
         initially been installed in the same orig_prefix.  But we can do
398
 
         better, to also cover the cases that 1. it has been installed
399
 
         in a different prefix before being moved to orig_prefix and (later)
400
 
         to curr_prefix, 2. unlike the program, it has not moved away from
401
 
         orig_prefix.  */
402
 
      const char *orig_installprefix = INSTALLPREFIX;
403
 
      const char *orig_installdir = INSTALLDIR;
404
 
      const char *curr_prefix_better;
405
 
 
406
 
      curr_prefix_better =
407
 
        compute_curr_prefix (orig_installprefix, orig_installdir,
408
 
                             get_shared_library_fullname ());
409
 
      if (curr_prefix_better == NULL)
410
 
        curr_prefix_better = curr_prefix;
411
 
 
412
 
      set_relocation_prefix (orig_installprefix, curr_prefix_better);
413
 
 
414
 
      initialized = 1;
415
 
    }
416
 
#endif
417
 
 
418
 
  /* Note: It is not necessary to perform case insensitive comparison here,
419
 
     even for DOS-like filesystems, because the pathname argument was
420
 
     typically created from the same Makefile variable as orig_prefix came
421
 
     from.  */
422
 
  if (orig_prefix != NULL && curr_prefix != NULL
423
 
      && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
424
 
    {
425
 
      if (pathname[orig_prefix_len] == '\0')
426
 
        /* pathname equals orig_prefix.  */
427
 
        return curr_prefix;
428
 
      if (ISSLASH (pathname[orig_prefix_len]))
429
 
        {
430
 
          /* pathname starts with orig_prefix.  */
431
 
          const char *pathname_tail = &pathname[orig_prefix_len];
432
 
          char *result =
433
 
            (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
434
 
 
435
 
#ifdef NO_XMALLOC
436
 
          if (result != NULL)
437
 
#endif
438
 
            {
439
 
              memcpy (result, curr_prefix, curr_prefix_len);
440
 
              strcpy (result + curr_prefix_len, pathname_tail);
441
 
              return result;
442
 
            }
443
 
        }
444
 
    }
445
 
  /* Nothing to relocate.  */
446
 
  return pathname;
447
 
}
448
 
 
449
 
#endif