Extensive OID code enhancement and fixes.
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index e56f3de..9c61829 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -58,6 +58,7 @@
 
 #include <stdio.h>
 #include <ctype.h>
+#include <limits.h>
 #include "cryptlib.h"
 #include <openssl/lhash.h>
 #include <openssl/asn1.h>
@@ -413,8 +414,8 @@
 	/* Work out size of content octets */
 	i=a2d_ASN1_OBJECT(NULL,0,s,-1);
 	if (i <= 0) {
-		/* Clear the error */
-		ERR_clear_error();
+		/* Don't clear the error */
+		/*ERR_clear_error();*/
 		return NULL;
 	}
 	/* Work out total size */
@@ -436,66 +437,145 @@
 
 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
 {
-	int i,idx=0,n=0,len,nid;
+	int i,n=0,len,nid, first, use_bn;
+	BIGNUM *bl;
 	unsigned long l;
 	unsigned char *p;
-	const char *s;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
-	if (buf_len <= 0) return(0);
-
 	if ((a == NULL) || (a->data == NULL)) {
 		buf[0]='\0';
 		return(0);
 	}
 
-	if (no_name || (nid=OBJ_obj2nid(a)) == NID_undef) {
-		len=a->length;
-		p=a->data;
 
-		idx=0;
-		l=0;
-		while (idx < a->length) {
-			l|=(p[idx]&0x7f);
-			if (!(p[idx] & 0x80)) break;
-			l<<=7L;
-			idx++;
-		}
-		idx++;
-		i=(int)(l/40);
-		if (i > 2) i=2;
-		l-=(long)(i*40);
-
-		BIO_snprintf(tbuf,sizeof tbuf,"%d.%lu",i,l);
-		i=strlen(tbuf);
-		BUF_strlcpy(buf,tbuf,buf_len);
-		buf_len-=i;
-		buf+=i;
-		n+=i;
-
-		l=0;
-		for (; idx<len; idx++) {
-			l|=p[idx]&0x7f;
-			if (!(p[idx] & 0x80)) {
-				BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
-				i=strlen(tbuf);
-				if (buf_len > 0)
-					BUF_strlcpy(buf,tbuf,buf_len);
-				buf_len-=i;
-				buf+=i;
-				n+=i;
-				l=0;
-			}
-			l<<=7L;
-		}
-	} else {
+	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
+		{
+		const char *s;
 		s=OBJ_nid2ln(nid);
 		if (s == NULL)
 			s=OBJ_nid2sn(nid);
-		BUF_strlcpy(buf,s,buf_len);
+		if (buf)
+			BUF_strlcpy(buf,s,buf_len);
 		n=strlen(s);
-	}
-	return(n);
+		return n;
+		}
+
+
+	len=a->length;
+	p=a->data;
+
+	first = 1;
+	bl = NULL;
+
+	while (len > 0)
+		{
+		l=0;
+		use_bn = 0;
+		for (;;)
+			{
+			unsigned char c = *p++;
+			len--;
+			if ((len == 0) && (c & 0x80))
+				goto err;
+			if (use_bn)
+				{
+				if (!BN_add_word(bl, c & 0x7f))
+					goto err;
+				}
+			else
+				l |= c  & 0x7f;
+			if (!(c & 0x80))
+				break;
+			if (!use_bn && (l > (ULONG_MAX >> 7L)))
+				{
+				if (!bl && !(bl = BN_new()))
+					goto err;
+				if (!BN_set_word(bl, l))
+					goto err;
+				use_bn = 1;
+				}
+			if (use_bn)
+				{
+				if (!BN_lshift(bl, bl, 7))
+					goto err;
+				}
+			else
+				l<<=7L;
+			}
+
+		if (first)
+			{
+			first = 0;
+			if (l >= 80)
+				{
+				i = 2;
+				if (use_bn)
+					{
+					if (!BN_sub_word(bl, 80))
+						goto err;
+					}
+				else
+					l -= 80;
+				}
+			else
+				{
+				i=(int)(l/40);
+				l-=(long)(i*40);
+				}
+			if (buf && (buf_len > 0))
+				{
+				*buf++ = i + '0';
+				buf_len--;
+				}
+			n++;
+			}
+
+		if (use_bn)
+			{
+			char *bndec;
+			bndec = BN_bn2dec(bl);
+			if (!bndec)
+				goto err;
+			i = strlen(bndec);
+			if (buf)
+				{
+				if (buf_len > 0)
+					{
+					*buf++ = '.';
+					buf_len--;
+					}
+				BUF_strlcpy(buf,bndec,buf_len);
+				buf += i;
+				}
+			n++;
+			n += i;
+			buf_len -= i;
+			OPENSSL_free(bndec);
+			}
+		else
+			{
+			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
+			i=strlen(tbuf);
+			if (buf && (buf_len > 0))
+				{
+				BUF_strlcpy(buf,tbuf,buf_len);
+				buf+=i;
+				}
+			buf_len-=i;
+			n+=i;
+			l=0;
+			}
+		}
+
+	if (bl)
+		BN_free(bl);
+	return n;
+
+	err:
+	if (bl)
+		BN_free(bl);
+	return -1;
 }
 
 int OBJ_txt2nid(const char *s)