From 5b64006f8adb92a9e8d44596e89a32e65af58ab6 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Fri, 16 Sep 2011 01:09:39 +0200
Subject: [PATCH] Bugfix in unicode.c affected sapG on big-endian. Related fixes to SybaseASE and Oracle

---
 src/SybaseASE_fmt.c   |   14 ++---------
 src/oracle_fmt_plug.c |   21 ++++++----------
 src/unicode.c         |   59 +++++++++++++++++++++++++++---------------------
 3 files changed, 44 insertions(+), 50 deletions(-)

diff --git a/src/SybaseASE_fmt.c b/src/SybaseASE_fmt.c
index 798f287..8ffc1fb 100644
--- a/src/SybaseASE_fmt.c
+++ b/src/SybaseASE_fmt.c
@@ -171,20 +171,12 @@ static void set_salt(void *salt)
 
 static void set_key(char *key, int index)
 {
-    UTF16 *c;
-
     /* Clean slate */
     memset(prep_key[index], 0, 2 * PLAINTEXT_LENGTH);
 
-    /* convert key to UTF-16 - encoding aware */
-    enc_to_utf16(prep_key[index], PLAINTEXT_LENGTH, (UTF8*)key,
-                 strlen(key));
-
-    // Byte-swap to UTF-16BE
-    // This should be made optional in enc_to_utf16, for speed
-    c = prep_key[index];
-    while ((*c = *c >> 8 | *c << 8))
-        c++;
+    /* convert key to UTF-16BE, --encoding aware */
+    enc_to_utf16_be(prep_key[index], PLAINTEXT_LENGTH, (UTF8*)key,
+                    strlen(key));
 }
 
 static char *get_key(int index)
diff --git a/src/oracle_fmt_plug.c b/src/oracle_fmt_plug.c
index 73b396e..25d8caf 100644
--- a/src/oracle_fmt_plug.c
+++ b/src/oracle_fmt_plug.c
@@ -133,7 +133,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *pFmt)
 		// utf8 string.
 		MEM_FREE(cp);
 
-		// Upcase user name (in --encoding=utf8 mode if requested).
+		// Upcase user name, --encoding aware
 		utf8len = enc_uc(tmp8, 16*3, (unsigned char*)split_fields[0], strlen(split_fields[0]));
 
 		if (utf8len <= 0 && split_fields[0][0])
@@ -179,10 +179,10 @@ static void oracle_set_salt(void *salt) {
 }
 
 static void oracle_set_key(char *key, int index) {
-	int i = 0;
 	UTF16 cur_key_mixedcase[PLAINTEXT_LENGTH+1];
 
 	plain_key = key;
+	// Can't use enc_to_utf16_be() because we need to do utf16_uc later
 	key_length = enc_to_utf16((UTF16 *)cur_key_mixedcase, PLAINTEXT_LENGTH, (unsigned char*)key, strlen(key));
 
 	if (key_length <= 0)
@@ -195,12 +195,11 @@ static void oracle_set_key(char *key, int index) {
 	if (key_length < 0)
 		key_length *= -1;
 
-	// This must be byte-swapped to UTF-16BE
+	// This must be byte-swapped on LE systems only (odd!?)
 #if ARCH_LITTLE_ENDIAN
-	for(;i<key_length;i++) {
-		UTF16 *c = &cur_key[i];
-		*c = (*c << 8) | (*c >> 8);
-	}
+	UTF16 *c = cur_key;
+	while((*c = *c << 8 | *c >> 8))
+		c++;
 #endif
 	key_length *= sizeof(UTF16);
 
@@ -264,7 +263,7 @@ static void * oracle_get_salt(char * ciphertext)
 {
 	static UTF16 *out;
 	UTF8 salt[SALT_SIZE + 1];
-	int i, l;
+	int l;
 
 	if (!out) out = mem_alloc_tiny(SALT_SIZE+2, MEM_ALIGN_WORD);
 	l = 2;
@@ -278,14 +277,10 @@ static void * oracle_get_salt(char * ciphertext)
 
 	// we now upcase the user name in the prepare() function.
 	// So we are going back to 'simple' plain->utf16 convert only.
-	l = enc_to_utf16(&out[1], 16, (UTF8 *)salt, l-2);
+	l = enc_to_utf16_be(&out[1], 16, (UTF8 *)salt, l-2);
 	if (l <= 0)
 		l = strlen16(&out[1]);
 
-	// This must be byte-swapped regardless of arch endianness
-	for(i=1;i<=l;i++) {
-		out[i] = (out[i] << 8) | (out[i] >> 8);
-	}
 	out[0] = (l<<1);
 	return out;
 }
diff --git a/src/unicode.c b/src/unicode.c
index 10c529b..7f1924c 100644
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -90,9 +90,9 @@ UTF16 ucs2_downcase[0x10000];
  * These array values are properly filled in at init() once we know the proper code page the user is using.
  */
 UTF16 CP_to_Unicode[0x100];
-static UTF8  CP_from_Unicode[0x10000];
-UTF8  CP_up[0x100];
-UTF8  CP_down[0x100];
+static UTF8 CP_from_Unicode[0x10000];
+UTF8 CP_up[0x100];
+UTF8 CP_down[0x100];
 static int UnicodeType = -1;
 
 /*
@@ -147,7 +147,7 @@ struct opts options;
 
 /*
  * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow.  There are
+ * into the first byte, depending on how many bytes follow. There are
  * as many entries in this table as there are UTF-8 sequence types.
  * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
  * for *legal* UTF-8 will be 4 or fewer bytes total.
@@ -195,8 +195,8 @@ static const UTF32 halfMask = 0x3FFUL;
 // instead, so we can truncate our saved_plain or whatever accordingly.
 //
 // The original function in ConvertUTF.c is called ConvertUTF8toUTF16()
-inline int utf8_to_utf16(UTF16 * target, unsigned int len, const UTF8 * source,
-                     unsigned int sourceLen)
+inline int utf8_to_utf16(UTF16 *target, unsigned int len, const UTF8 *source,
+                         unsigned int sourceLen)
 {
 	const UTF16 *targetStart = target;
 	const UTF16 *targetEnd = target + len;
@@ -208,7 +208,7 @@ inline int utf8_to_utf16(UTF16 * target, unsigned int len, const UTF8 * source,
 	while (source < sourceEnd) {
 		if (*source < 0xC0) {
 #if ARCH_LITTLE_ENDIAN
-			*target++ = (UTF16) * source++;
+			*target++ = (UTF16) *source++;
 #else
 			UTF8 val = *source++;
 			SSVAL(target, 0, val);
@@ -304,7 +304,7 @@ inline int utf8_to_utf16(UTF16 * target, unsigned int len, const UTF8 * source,
 //NOTE, Solaris did not build properly with this function inlined. Thus
 // the inline was removed (for now).
 //inline
-int enc_to_utf16_be(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src, unsigned int srclen) {
+int enc_to_utf16_be(UTF16 *dst, unsigned int maxdstlen, const UTF8 *src, unsigned int srclen) {
 	if (!(options.utf8)) {
 		int i, trunclen = (int)srclen;
 		if (trunclen > maxdstlen)
@@ -312,9 +312,8 @@ int enc_to_utf16_be(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src, unsig
 
 		for (i = 0; i < trunclen; i++) {
 #if ARCH_LITTLE_ENDIAN
-			UTF16 val = CP_to_Unicode[*src++];
-			SSVAL(dst, 0, val);
-			++dst;
+			*dst++ = CP_to_Unicode[*src] >> 8 | CP_to_Unicode[*src] << 8;
+			src++;
 #else
 			*dst++ = CP_to_Unicode[*src++];
 #endif
@@ -325,11 +324,19 @@ int enc_to_utf16_be(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src, unsig
 		else
 			return i;
 	} else {		// Convert from UTF-8
-		return utf8_to_utf16(dst, maxdstlen, src, srclen);
+		int len;
+
+		len = utf8_to_utf16(dst, maxdstlen, src, srclen);
+
+		// Byte-swap to UTF-16BE
+		while ((*dst = *dst >> 8 | *dst << 8))
+			dst++;
+
+		return len;
 	}
 }
-int enc_to_utf16(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src,
-                      unsigned int srclen)
+int enc_to_utf16(UTF16 *dst, unsigned int maxdstlen, const UTF8 *src,
+                 unsigned int srclen)
 {
 	if (!(options.utf8)) {
 		int i, trunclen = (int)srclen;
@@ -356,7 +363,7 @@ int enc_to_utf16(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src,
 }
 
 // strlen of UTF16 (in characters, not bytes)
-inline unsigned int strlen16(const UTF16 * str)
+inline unsigned int strlen16(const UTF16 *str)
 {
 	unsigned int len = 0;
 	while (*str++ != 0)
@@ -378,7 +385,7 @@ inline unsigned int strlen16(const UTF16 * str)
  *
  * This is now thread-safe
  */
-int E_md4hash(const UTF8 * passwd, unsigned int len, unsigned char *p16)
+int E_md4hash(const UTF8 *passwd, unsigned int len, unsigned char *p16)
 {
 	int trunclen;
 	UTF16 wpwd[PLAINTEXT_BUFFER_SIZE + 1];
@@ -505,13 +512,13 @@ int E_md4hash(const UTF8 * passwd, unsigned int len, unsigned char *p16)
 // Convert UTF-16LE to UTF-8. This is not optimised as it's
 // only used in get_key() as of now.
 // Non thread-safe version
-UTF8 * utf16_to_utf8 (const UTF16* source) {
+UTF8 *utf16_to_utf8 (const UTF16 *source) {
 	static UTF8 ret_Key[PLAINTEXT_BUFFER_SIZE + 1];
 	return utf16_to_utf8_r(ret_Key, PLAINTEXT_BUFFER_SIZE, source);
 }
 
 // Thread-safe version
-UTF8 * utf16_to_utf8_r (UTF8 *dst, int dst_len, const UTF16* source) {
+UTF8 *utf16_to_utf8_r (UTF8 *dst, int dst_len, const UTF16 *source) {
 	UTF8 *tpt = dst;
 	UTF8 *targetEnd = tpt + dst_len;
 	while (*source) {
@@ -519,7 +526,7 @@ UTF8 * utf16_to_utf8_r (UTF8 *dst, int dst_len, const UTF16* source) {
 		unsigned short bytesToWrite = 0;
 		const UTF32 byteMask = 0xBF;
 		const UTF32 byteMark = 0x80;
-		const UTF16* oldSource = source; /* In case we have to back out */
+		const UTF16 *oldSource = source; /* In case we have to back out */
 		ch = *source++;
 		/* If we have a surrogate pair, convert to UTF32 first. */
 		if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
@@ -569,11 +576,11 @@ UTF8 * utf16_to_utf8_r (UTF8 *dst, int dst_len, const UTF16* source) {
 }
 
 /* Thread-safe conversion from codepage to UTF-8 */
-UTF8 * enc_to_utf8_r (char *src, UTF8* dst)
+UTF8 *enc_to_utf8_r (char *src, UTF8 *dst)
 {
 	UTF16 tmp16[PLAINTEXT_BUFFER_SIZE + 1];
 	enc_to_utf16(tmp16, PLAINTEXT_BUFFER_SIZE, (unsigned char*)src,
-	           PLAINTEXT_BUFFER_SIZE);
+	             PLAINTEXT_BUFFER_SIZE);
 	dst = utf16_to_utf8_r(dst, PLAINTEXT_BUFFER_SIZE, tmp16);
 	return dst;
 }
@@ -583,7 +590,7 @@ char * utf8_to_enc_r (UTF8 *src, char* dst)
 {
 	UTF16 tmp16[PLAINTEXT_BUFFER_SIZE + 1];
 	utf8_to_utf16(tmp16, PLAINTEXT_BUFFER_SIZE, (unsigned char*)src,
-	           PLAINTEXT_BUFFER_SIZE);
+	              PLAINTEXT_BUFFER_SIZE);
 	dst = (char*)utf16_to_plain_r((UTF8*)dst, PLAINTEXT_BUFFER_SIZE, tmp16);
 	return dst;
 }
@@ -591,13 +598,13 @@ char * utf8_to_enc_r (UTF8 *src, char* dst)
 // Convert UTF-16LE to UTF-8 or ISO-8859-1 depending on --encoding=utf8 flag.
 // This is not optimised as it's only used in get_key() as of now.
 // Non thread-safe version
-UTF8 * utf16_to_enc (const UTF16* source) {
+UTF8 *utf16_to_enc (const UTF16 *source) {
 	static UTF8 ret_Key[PLAINTEXT_BUFFER_SIZE + 1];
 	return utf16_to_plain_r(ret_Key, PLAINTEXT_BUFFER_SIZE, source);
 }
 
 // Thread-safe version
-UTF8 * utf16_to_plain_r (UTF8 *dst, int dst_len, const UTF16* source) {
+UTF8 *utf16_to_plain_r (UTF8 *dst, int dst_len, const UTF16 *source) {
 	if (options.utf8)
 		return utf16_to_utf8_r(dst, dst_len, source);
 	else {
@@ -848,10 +855,10 @@ int initUnicode(int type) {
 //_inline UTF16 up2low_u16(UTF16 w) {if (ucs2_downcase[w]) return ucs2_downcase[w]; return w; }
 
 /* Convert to UTF-16LE from UTF-8 or ISO-8859-1 depending on --encoding=utf8 flag, and upcase/lowcase at same time */
-//int plain_to_utf16_uc(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src, unsigned int srclen) {
+//int plain_to_utf16_uc(UTF16 *dst, unsigned int maxdstlen, const UTF8 *src, unsigned int srclen) {
 //	return 0;
 //}
-//int plain_to_utf16_lc(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src, unsigned int srclen) {
+//int plain_to_utf16_lc(UTF16 *dst, unsigned int maxdstlen, const UTF8 *src, unsigned int srclen) {
 //	return 0;
 //}
 
-- 
1.7.4.1

