summary refs log tree commit diff
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-06-22 23:59:32 +0000
committerUlrich Drepper <drepper@redhat.com>2006-06-22 23:59:32 +0000
commit4259230fd19559ba398ff40c117fa43089003b51 (patch)
tree4307f68fc12a00733e92f878ff50bc40480a6692 /intl/dcigettext.c
parentf9b7a98b18c8c1dc20744e86352f0447a2cf2e77 (diff)
downloadglibc-4259230fd19559ba398ff40c117fa43089003b51.tar.gz
glibc-4259230fd19559ba398ff40c117fa43089003b51.tar.xz
glibc-4259230fd19559ba398ff40c117fa43089003b51.zip
* intl/dcigettext.c (DCIGETTEXT): If _nl_find_msg returns -1 don't
	look further, return original strings.
	(_nl_find_msg): Do not return found translation if the conversion
	failed.  Either signal the string is unusable or that something went
	wrong and the original should be used.

2006-06-21  Ulrich Drepper  <drepper@redhat.com>

	* string/_strerror.c (__strerror_r): Add __builtin_expect.
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r--intl/dcigettext.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index b56196ccbe..cb2b1813a7 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -611,6 +611,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
       if (strcmp (single_locale, "C") == 0
 	  || strcmp (single_locale, "POSIX") == 0)
 	{
+	no_translation:
 	  FREE_BLOCKS (block_list);
 	  __libc_rwlock_unlock (_nl_state_lock);
 	  __set_errno (saved_errno);
@@ -646,6 +647,12 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 		}
 	    }
 
+	  /* Returning -1 means that some resource problem exists
+	     (likely memory) and that the strings could not be
+	     converted.  Return the original strings.  */
+	  if (__builtin_expect (retval == (char *) -1, 0))
+	    goto no_translation;
+
 	  if (retval != NULL)
 	    {
 	      /* Found the translation of MSGID1 in domain DOMAIN:
@@ -865,21 +872,22 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	     encoding.  */
 	  struct converted_domain *new_conversions =
 	    (struct converted_domain *)
-	    (domain->conversions != NULL
-	     ? realloc (domain->conversions,
-			(nconversions + 1) * sizeof (struct converted_domain))
-	     : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
+	    realloc (domain->conversions,
+		     (nconversions + 1) * sizeof (struct converted_domain));
 
 	  if (__builtin_expect (new_conversions == NULL, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
+
 	  domain->conversions = new_conversions;
 
 	  /* Copy the 'encoding' string to permanent storage.  */
 	  encoding = strdup (encoding);
 	  if (__builtin_expect (encoding == NULL, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
 
 	  convd = &new_conversions[nconversions];
 	  convd->encoding = encoding;
@@ -933,10 +941,18 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		    /* We always want to use transliteration.  */
 		    outcharset = norm_add_slashes (outcharset, "TRANSLIT");
 		    charset = norm_add_slashes (charset, "");
-		    if (__gconv_open (outcharset, charset, &convd->conv,
-				      GCONV_AVOID_NOCONV)
-			!= __GCONV_OK)
-		      convd->conv = (__gconv_t) -1;
+		    int r = __gconv_open (outcharset, charset, &convd->conv,
+					  GCONV_AVOID_NOCONV);
+		    if (__builtin_expect (r != __GCONV_OK, 0))
+		      {
+			/* If the output encoding is the same there is
+			   nothing to do.  Otherwise do not use the
+			   translation at all.  */
+			if (__builtin_expect (r != __GCONV_NOCONV, 1))
+			  return NULL;
+
+			convd->conv = (__gconv_t) -1;
+		      }
 # else
 #  if HAVE_ICONV
 		    /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
@@ -1000,8 +1016,9 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	    convd->conv_tab = (char **) -1;
 
 	  if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
-	    /* Nothing we can do, no more memory.  */
-	    goto converted;
+	    /* Nothing we can do, no more memory.  We cannot use the
+	       translation because it might be encoded incorrectly.  */
+	    return (char *) -1;
 
 	  if (convd->conv_tab[act] == NULL)
 	    {
@@ -1049,8 +1066,10 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 
 		  if (res != __GCONV_FULL_OUTPUT)
 		    {
+		      /* We should not use the translation at all, it
+			 is incorrectly encoded.  */
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return NULL;
 		    }
 
 		  inbuf = (const unsigned char *) result;
@@ -1076,7 +1095,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		  if (errno != E2BIG)
 		    {
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return NULL;
 		    }
 #  endif
 # endif
@@ -1112,7 +1131,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 		      freemem = NULL;
 		      freemem_size = 0;
 		      __libc_lock_unlock (lock);
-		      goto converted;
+		      return (char *) -1;
 		    }
 
 # ifdef _LIBC
@@ -1151,7 +1170,6 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
 	}
     }
 
- converted:
   /* The result string is converted.  */
 
 #endif /* _LIBC || HAVE_ICONV */