summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjgmyers%speakeasy.net <devnull@localhost>2004-01-15 06:23:14 +0000
committerjgmyers%speakeasy.net <devnull@localhost>2004-01-15 06:23:14 +0000
commitcbb0b657eb8b6715a688b308dd5b24b7c23c153c (patch)
tree4e1aea62d0ce344ec8528a3ed649892e04795267
parent1f308d745f87b7f98f12fa6745633a6631534478 (diff)
downloadnss-hg-cbb0b657eb8b6715a688b308dd5b24b7c23c153c.tar.gz
Convert T61String-labeled ISO-8859-1 to UTF-8: bug 53133 r=nelsonb a=wtc
-rw-r--r--security/nss/lib/certdb/secname.c68
-rw-r--r--security/nss/lib/util/secport.c9
-rw-r--r--security/nss/lib/util/secport.h16
-rw-r--r--security/nss/lib/util/utf8.c97
4 files changed, 161 insertions, 29 deletions
diff --git a/security/nss/lib/certdb/secname.c b/security/nss/lib/certdb/secname.c
index 5a40249da..d1abab4fa 100644
--- a/security/nss/lib/certdb/secname.c
+++ b/security/nss/lib/certdb/secname.c
@@ -17,6 +17,7 @@
* Rights Reserved.
*
* Contributor(s):
+ * John Gardiner Myers <jgmyers@speakeasy.net>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
@@ -603,8 +604,7 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue)
{
SECItem *retItem;
const SEC_ASN1Template *theTemplate = NULL;
- PRBool convertUCS4toUTF8 = PR_FALSE;
- PRBool convertUCS2toUTF8 = PR_FALSE;
+ enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none;
SECItem avaValue = {siBuffer, 0};
PLArenaPool *newarena = NULL;
@@ -614,7 +614,7 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue)
switch(derAVAValue->data[0]) {
case SEC_ASN1_UNIVERSAL_STRING:
- convertUCS4toUTF8 = PR_TRUE;
+ convert = conv_ucs4;
theTemplate = SEC_UniversalStringTemplate;
break;
case SEC_ASN1_IA5_STRING:
@@ -624,10 +624,15 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue)
theTemplate = SEC_PrintableStringTemplate;
break;
case SEC_ASN1_T61_STRING:
+ /*
+ * Per common practice, we're not decoding actual T.61, but instead
+ * treating T61-labeled strings as containing ISO-8859-1.
+ */
+ convert = conv_iso88591;
theTemplate = SEC_T61StringTemplate;
break;
case SEC_ASN1_BMP_STRING:
- convertUCS2toUTF8 = PR_TRUE;
+ convert = conv_ucs2;
theTemplate = SEC_BMPStringTemplate;
break;
case SEC_ASN1_UTF8_STRING:
@@ -649,36 +654,41 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue)
return NULL;
}
- if (convertUCS4toUTF8) {
+ if (convert != conv_none) {
unsigned int utf8ValLen = avaValue.len * 3;
unsigned char *utf8Val = (unsigned char*)
PORT_ArenaZAlloc(newarena, utf8ValLen);
- if(avaValue.len % 4 != 0 ||
- !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
- utf8Val, utf8ValLen, &utf8ValLen)) {
- PORT_FreeArena(newarena, PR_FALSE);
- PORT_SetError(SEC_ERROR_INVALID_AVA);
- return NULL;
+ switch (convert) {
+ case conv_ucs4:
+ if(avaValue.len % 4 != 0 ||
+ !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
+ utf8Val, utf8ValLen, &utf8ValLen)) {
+ PORT_FreeArena(newarena, PR_FALSE);
+ PORT_SetError(SEC_ERROR_INVALID_AVA);
+ return NULL;
+ }
+ break;
+ case conv_ucs2:
+ if(avaValue.len % 2 != 0 ||
+ !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
+ utf8Val, utf8ValLen, &utf8ValLen)) {
+ PORT_FreeArena(newarena, PR_FALSE);
+ PORT_SetError(SEC_ERROR_INVALID_AVA);
+ return NULL;
+ }
+ break;
+ case conv_iso88591:
+ if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len,
+ utf8Val, utf8ValLen, &utf8ValLen)) {
+ PORT_FreeArena(newarena, PR_FALSE);
+ PORT_SetError(SEC_ERROR_INVALID_AVA);
+ return NULL;
+ }
+ break;
+ case conv_none: ;
}
-
- avaValue.data = utf8Val;
- avaValue.len = utf8ValLen;
-
- } else if (convertUCS2toUTF8) {
-
- unsigned int utf8ValLen = avaValue.len * 3;
- unsigned char *utf8Val = (unsigned char*)
- PORT_ArenaZAlloc(newarena, utf8ValLen);
-
- if(avaValue.len % 2 != 0 ||
- !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
- utf8Val, utf8ValLen, &utf8ValLen)) {
- PORT_FreeArena(newarena, PR_FALSE);
- PORT_SetError(SEC_ERROR_INVALID_AVA);
- return NULL;
- }
-
+
avaValue.data = utf8Val;
avaValue.len = utf8ValLen;
}
diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c
index 7d276f9b7..1abf5c030 100644
--- a/security/nss/lib/util/secport.c
+++ b/security/nss/lib/util/secport.c
@@ -542,6 +542,15 @@ PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
}
PRBool
+PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen)
+{
+ return sec_port_iso88591_utf8_conversion_function(inBuf, inBufLen,
+ outBuf, maxOutBufLen, outBufLen);
+}
+
+PRBool
PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf,
unsigned int inBufLen, unsigned char *outBuf,
unsigned int maxOutBufLen, unsigned int *outBufLen,
diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h
index 5cfdbd19d..693b35110 100644
--- a/security/nss/lib/util/secport.h
+++ b/security/nss/lib/util/secport.h
@@ -255,6 +255,11 @@ PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
unsigned int inBufLen, unsigned char *outBuf,
unsigned int maxOutBufLen, unsigned int *outBufLen);
+/* One-way conversion from ISO-8859-1 to UTF-8 */
+PRBool PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen);
+
PR_EXTERN(PRBool)
sec_port_ucs4_utf8_conversion_function
(
@@ -277,6 +282,17 @@ sec_port_ucs2_utf8_conversion_function
unsigned int *outBufLen
);
+/* One-way conversion from ISO-8859-1 to UTF-8 */
+extern PRBool
+sec_port_iso88591_utf8_conversion_function
+(
+ const unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen
+);
+
extern int NSS_PutEnv(const char * envVarName, const char * envValue);
SEC_END_PROTOS
diff --git a/security/nss/lib/util/utf8.c b/security/nss/lib/util/utf8.c
index 013f202a9..f418233eb 100644
--- a/security/nss/lib/util/utf8.c
+++ b/security/nss/lib/util/utf8.c
@@ -17,6 +17,7 @@
* Rights Reserved.
*
* Contributor(s):
+ * John Gardiner Myers <jgmyers@speakeasy.net>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
@@ -553,6 +554,56 @@ sec_port_ucs2_utf8_conversion_function
}
}
+PRBool
+sec_port_iso88591_utf8_conversion_function
+(
+ const unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen
+)
+{
+#ifndef TEST_UTF8
+ PORT_Assert((unsigned int *)NULL != outBufLen);
+#endif /* TEST_UTF8 */
+
+ unsigned int i, len = 0;
+
+ for( i = 0; i < inBufLen; i++) {
+ if( (inBuf[i] & 0x80) == 0x00 ) len += 1;
+ else len += 2;
+ }
+
+ if( len > maxOutBufLen ) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for( i = 0; i < inBufLen; i++) {
+ if( (inBuf[i] & 0x80) == 0x00 ) {
+ /* 7F -> 0xxxxxx */
+ /* 0abcdefg -> 0abcdefg */
+
+ outBuf[len] = inBuf[i];
+ len += 1;
+ } else {
+ /* 80-FF <- 110xxxxx 10xxxxxx */
+ /* 00000000 abcdefgh -> 110000ab 10cdefgh */
+
+ outBuf[len+0] = 0xC0 | ((inBuf[i] & 0xC0) >> 6);
+ outBuf[len+1] = 0x80 | ((inBuf[i] & 0x3F) >> 0);
+
+ len += 2;
+ }
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+}
+
#ifdef TEST_UTF8
#include <stdio.h>
@@ -1743,6 +1794,51 @@ test_utf16_chars
#endif /* UTF16 */
static PRBool
+test_iso88591_chars
+(
+ void
+)
+{
+ PRBool rv = PR_TRUE;
+ int i;
+
+ for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
+ struct ucs2 *e = &ucs2[i];
+ PRBool result;
+ unsigned char iso88591;
+ unsigned char utf8[8];
+ unsigned int len = 0;
+
+ if (e->c > 0xFF) continue;
+
+ (void)memset(utf8, 0, sizeof(utf8));
+ iso88591 = e->c;
+
+ result = sec_port_iso88591_utf8_conversion_function(&iso88591,
+ 1, utf8, sizeof(utf8), &len);
+
+ if( !result ) {
+ fprintf(stdout, "Failed to convert ISO-8859-1 0x%02.2x to UTF-8\n", iso88591);
+ rv = PR_FALSE;
+ continue;
+ }
+
+ if( (len >= sizeof(utf8)) ||
+ (strlen(e->utf8) != len) ||
+ (utf8[len] = '\0', 0 != strcmp(e->utf8, utf8)) ) {
+ fprintf(stdout, "Wrong conversion of ISO-8859-1 0x%02.2x to UTF-8: ", iso88591);
+ dump_utf8("expected", e->utf8, ", ");
+ dump_utf8("received", utf8, "\n");
+ rv = PR_FALSE;
+ continue;
+ }
+
+ }
+
+ return rv;
+}
+
+static PRBool
test_zeroes
(
void
@@ -2057,6 +2153,7 @@ main
#ifdef UTF16
test_utf16_chars() &&
#endif /* UTF16 */
+ test_iso88591_chars() &&
test_zeroes() &&
test_multichars() &&
PR_TRUE ) {