~ubuntu-branches/ubuntu/hardy/gnupg2/hardy

« back to all changes in this revision

Viewing changes to intl/loadmsgcat.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Bienia, Michael Bienia, Kees Cook
  • Date: 2006-12-07 00:28:23 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20061207002823-0i7ittrpmsm1nv0i
Tags: 2.0.1-0ubuntu1
[ Michael Bienia ]
* New upstream version.
* Remaining changes:
  - Remove libpcsclite-dev, libopensc2-dev build dependencies (they are in
    universe).
* g10/encr-data.c: remotely controllable function pointer (CVE-2006-6235)
* debian/control: add libcurl3-gnutls-dev to build-depends 
  (Closes Ubuntu: #62864)

[ Kees Cook ]
* debian/rules: include doc/ files as done with gnupg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Load needed message catalogs.
2
 
   Copyright (C) 1995-1999, 2000-2004 Free Software Foundation, Inc.
 
2
   Copyright (C) 1995-1999, 2000-2005 Free Software Foundation, Inc.
3
3
 
4
4
   This program is free software; you can redistribute it and/or modify it
5
5
   under the terms of the GNU Library General Public License as published
13
13
 
14
14
   You should have received a copy of the GNU Library General Public
15
15
   License along with this program; if not, write to the Free Software
16
 
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
16
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17
17
   USA.  */
18
18
 
19
19
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
91
91
 
92
92
#ifdef _LIBC
93
93
# include "../locale/localeinfo.h"
 
94
# include <not-cancel.h>
 
95
#endif
 
96
 
 
97
/* Handle multi-threaded applications.  */
 
98
#ifdef _LIBC
 
99
# include <bits/libc-lock.h>
 
100
#else
 
101
# include "lock.h"
94
102
#endif
95
103
 
96
104
/* Provide fallback values for macros that ought to be defined in <inttypes.h>.
457
465
/* Rename the non ISO C functions.  This is required by the standard
458
466
   because some ISO C functions will require linking with this object
459
467
   file and the name space must not be polluted.  */
460
 
# define open   __open
461
 
# define close  __close
462
 
# define read   __read
463
 
# define mmap   __mmap
464
 
# define munmap __munmap
 
468
# define open(name, flags)      open_not_cancel_2 (name, flags)
 
469
# define close(fd)              close_not_cancel_no_status (fd)
 
470
# define read(fd, buf, n)       read_not_cancel (fd, buf, n)
 
471
# define mmap(addr, len, prot, flags, fd, offset) \
 
472
  __mmap (addr, len, prot, flags, fd, offset)
 
473
# define munmap(addr, len)      __munmap (addr, len)
465
474
#endif
466
475
 
467
476
/* For those losing systems which don't have `alloca' we have to add
764
773
  return NULL;
765
774
}
766
775
 
767
 
/* Initialize the codeset dependent parts of an opened message catalog.
768
 
   Return the header entry.  */
769
 
const char *
770
 
internal_function
771
 
_nl_init_domain_conv (struct loaded_l10nfile *domain_file,
772
 
                      struct loaded_domain *domain,
773
 
                      struct binding *domainbinding)
774
 
{
775
 
  /* Find out about the character set the file is encoded with.
776
 
     This can be found (in textual form) in the entry "".  If this
777
 
     entry does not exist or if this does not contain the `charset='
778
 
     information, we will assume the charset matches the one the
779
 
     current locale and we don't have to perform any conversion.  */
780
 
  char *nullentry;
781
 
  size_t nullentrylen;
782
 
 
783
 
  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
784
 
  domain->codeset_cntr =
785
 
    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
786
 
#ifdef _LIBC
787
 
  domain->conv = (__gconv_t) -1;
788
 
#else
789
 
# if HAVE_ICONV
790
 
  domain->conv = (iconv_t) -1;
791
 
# endif
792
 
#endif
793
 
  domain->conv_tab = NULL;
794
 
 
795
 
  /* Get the header entry.  */
796
 
  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
797
 
 
798
 
  if (nullentry != NULL)
799
 
    {
800
 
#if defined _LIBC || HAVE_ICONV
801
 
      const char *charsetstr;
802
 
 
803
 
      charsetstr = strstr (nullentry, "charset=");
804
 
      if (charsetstr != NULL)
805
 
        {
806
 
          size_t len;
807
 
          char *charset;
808
 
          const char *outcharset;
809
 
 
810
 
          charsetstr += strlen ("charset=");
811
 
          len = strcspn (charsetstr, " \t\n");
812
 
 
813
 
          charset = (char *) alloca (len + 1);
814
 
# if defined _LIBC || HAVE_MEMPCPY
815
 
          *((char *) mempcpy (charset, charsetstr, len)) = '\0';
816
 
# else
817
 
          memcpy (charset, charsetstr, len);
818
 
          charset[len] = '\0';
819
 
# endif
820
 
 
821
 
          /* The output charset should normally be determined by the
822
 
             locale.  But sometimes the locale is not used or not correctly
823
 
             set up, so we provide a possibility for the user to override
824
 
             this.  Moreover, the value specified through
825
 
             bind_textdomain_codeset overrides both.  */
826
 
          if (domainbinding != NULL && domainbinding->codeset != NULL)
827
 
            outcharset = domainbinding->codeset;
828
 
          else
829
 
            {
830
 
              outcharset = getenv ("OUTPUT_CHARSET");
831
 
              if (outcharset == NULL || outcharset[0] == '\0')
832
 
                {
833
 
# ifdef _LIBC
834
 
                  outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
835
 
# else
836
 
#  if HAVE_ICONV
837
 
                  extern const char *locale_charset (void);
838
 
                  outcharset = locale_charset ();
839
 
#  endif
840
 
# endif
841
 
                }
842
 
            }
843
 
 
844
 
# ifdef _LIBC
845
 
          /* We always want to use transliteration.  */
846
 
          outcharset = norm_add_slashes (outcharset, "TRANSLIT");
847
 
          charset = norm_add_slashes (charset, NULL);
848
 
          if (__gconv_open (outcharset, charset, &domain->conv,
849
 
                            GCONV_AVOID_NOCONV)
850
 
              != __GCONV_OK)
851
 
            domain->conv = (__gconv_t) -1;
852
 
# else
853
 
#  if HAVE_ICONV
854
 
          /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
855
 
             we want to use transliteration.  */
856
 
#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
857
 
       || _LIBICONV_VERSION >= 0x0105
858
 
          if (strchr (outcharset, '/') == NULL)
859
 
            {
860
 
              char *tmp;
861
 
 
862
 
              len = strlen (outcharset);
863
 
              tmp = (char *) alloca (len + 10 + 1);
864
 
              memcpy (tmp, outcharset, len);
865
 
              memcpy (tmp + len, "//TRANSLIT", 10 + 1);
866
 
              outcharset = tmp;
867
 
 
868
 
              domain->conv = iconv_open (outcharset, charset);
869
 
 
870
 
              freea (outcharset);
871
 
            }
872
 
          else
873
 
#   endif
874
 
            domain->conv = iconv_open (outcharset, charset);
875
 
#  endif
876
 
# endif
877
 
 
878
 
          freea (charset);
879
 
        }
880
 
#endif /* _LIBC || HAVE_ICONV */
881
 
    }
882
 
 
883
 
  return nullentry;
884
 
}
885
 
 
886
 
/* Frees the codeset dependent parts of an opened message catalog.  */
887
 
void
888
 
internal_function
889
 
_nl_free_domain_conv (struct loaded_domain *domain)
890
 
{
891
 
  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
892
 
    free (domain->conv_tab);
893
 
 
894
 
#ifdef _LIBC
895
 
  if (domain->conv != (__gconv_t) -1)
896
 
    __gconv_close (domain->conv);
897
 
#else
898
 
# if HAVE_ICONV
899
 
  if (domain->conv != (iconv_t) -1)
900
 
    iconv_close (domain->conv);
901
 
# endif
902
 
#endif
903
 
}
904
 
 
905
776
/* Load the message catalogs specified by FILENAME.  If it is no valid
906
777
   message catalog do nothing.  */
907
778
void
909
780
_nl_load_domain (struct loaded_l10nfile *domain_file,
910
781
                 struct binding *domainbinding)
911
782
{
912
 
  int fd;
 
783
  __libc_lock_define_initialized_recursive (static, lock)
 
784
  int fd = -1;
913
785
  size_t size;
914
786
#ifdef _LIBC
915
787
  struct stat64 st;
921
793
  struct loaded_domain *domain;
922
794
  int revision;
923
795
  const char *nullentry;
924
 
 
925
 
  domain_file->decided = 1;
 
796
  size_t nullentrylen;
 
797
 
 
798
  __libc_lock_lock_recursive (lock);
 
799
  if (domain_file->decided != 0)
 
800
    {
 
801
      /* There are two possibilities:
 
802
 
 
803
         + this is the same thread calling again during this initialization
 
804
           via _nl_find_msg.  We have initialized everything this call needs.
 
805
 
 
806
         + this is another thread which tried to initialize this object.
 
807
           Not necessary anymore since if the lock is available this
 
808
           is finished.
 
809
      */
 
810
      goto done;
 
811
    }
 
812
 
 
813
  domain_file->decided = -1;
926
814
  domain_file->data = NULL;
927
815
 
928
816
  /* Note that it would be useless to store domainbinding in domain_file
934
822
     specification the locale file name is different for XPG and CEN
935
823
     syntax.  */
936
824
  if (domain_file->filename == NULL)
937
 
    return;
 
825
    goto out;
938
826
 
939
827
  /* Try to open the addressed file.  */
940
828
  fd = open (domain_file->filename, O_RDONLY | O_BINARY);
941
829
  if (fd == -1)
942
 
    return;
 
830
    goto out;
943
831
 
944
832
  /* We must know about the size of the file.  */
945
833
  if (
950
838
#endif
951
839
      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
952
840
      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
953
 
    {
954
 
      /* Something went wrong.  */
955
 
      close (fd);
956
 
      return;
957
 
    }
 
841
    /* Something went wrong.  */
 
842
    goto out;
958
843
 
959
844
#ifdef HAVE_MMAP
960
845
  /* Now we are ready to load the file.  If mmap() is available we try
966
851
    {
967
852
      /* mmap() call was successful.  */
968
853
      close (fd);
 
854
      fd = -1;
969
855
      use_mmap = 1;
970
856
    }
971
857
#endif
979
865
 
980
866
      data = (struct mo_file_header *) malloc (size);
981
867
      if (data == NULL)
982
 
        return;
 
868
        goto out;
983
869
 
984
870
      to_read = size;
985
871
      read_ptr = (char *) data;
992
878
              if (nb == -1 && errno == EINTR)
993
879
                continue;
994
880
#endif
995
 
              close (fd);
996
 
              return;
 
881
              goto out;
997
882
            }
998
883
          read_ptr += nb;
999
884
          to_read -= nb;
1001
886
      while (to_read > 0);
1002
887
 
1003
888
      close (fd);
 
889
      fd = -1;
1004
890
    }
1005
891
 
1006
892
  /* Using the magic number we can test whether it really is a message
1015
901
      else
1016
902
#endif
1017
903
        free (data);
1018
 
      return;
 
904
      goto out;
1019
905
    }
1020
906
 
1021
907
  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
1022
908
  if (domain == NULL)
1023
 
    return;
 
909
    goto out;
1024
910
  domain_file->data = domain;
1025
911
 
1026
912
  domain->data = (char *) data;
1321
1207
                    for (i = 0; i < n_inmem_sysdep_strings; i++)
1322
1208
                      {
1323
1209
                        const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1324
 
                        nls_uint32 hash_val = hash_string (msgid);
 
1210
                        nls_uint32 hash_val = __hash_string (msgid);
1325
1211
                        nls_uint32 idx = hash_val % domain->hash_size;
1326
1212
                        nls_uint32 incr =
1327
1213
                          1 + (hash_val % (domain->hash_size - 2));
1382
1268
        free (data);
1383
1269
      free (domain);
1384
1270
      domain_file->data = NULL;
1385
 
      return;
 
1271
      goto out;
1386
1272
    }
1387
1273
 
1388
 
  /* Now initialize the character set converter from the character set
1389
 
     the file is encoded with (found in the header entry) to the domain's
1390
 
     specified character set or the locale's character set.  */
1391
 
  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
 
1274
  /* No caches of converted translations so far.  */
 
1275
  domain->conversions = NULL;
 
1276
  domain->nconversions = 0;
1392
1277
 
1393
 
  /* Also look for a plural specification.  */
 
1278
  /* Get the header entry and look for a plural specification.  */
 
1279
#ifdef IN_LIBGLOCALE
 
1280
  nullentry =
 
1281
    _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
 
1282
#else
 
1283
  nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
 
1284
#endif
1394
1285
  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
 
1286
 
 
1287
 out:
 
1288
  if (fd != -1)
 
1289
    close (fd);
 
1290
 
 
1291
  domain_file->decided = 1;
 
1292
 
 
1293
 done:
 
1294
  __libc_lock_unlock_recursive (lock);
1395
1295
}
1396
1296
 
1397
1297
 
1398
1298
#ifdef _LIBC
1399
1299
void
1400
 
internal_function
 
1300
internal_function __libc_freeres_fn_section
1401
1301
_nl_unload_domain (struct loaded_domain *domain)
1402
1302
{
 
1303
  size_t i;
 
1304
 
1403
1305
  if (domain->plural != &__gettext_germanic_plural)
1404
1306
    __gettext_free_exp (domain->plural);
1405
1307
 
1406
 
  _nl_free_domain_conv (domain);
 
1308
  for (i = 0; i < domain->nconversions; i++)
 
1309
    {
 
1310
      struct converted_domain *convd = &domain->conversions[i];
 
1311
 
 
1312
      free (convd->encoding);
 
1313
      if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
 
1314
        free (convd->conv_tab);
 
1315
      if (convd->conv != (__gconv_t) -1)
 
1316
        __gconv_close (convd->conv);
 
1317
    }
 
1318
  if (domain->conversions != NULL)
 
1319
    free (domain->conversions);
1407
1320
 
1408
1321
  if (domain->malloced)
1409
1322
    free (domain->malloced);