--- \\Debbie\ger\prj\1original\openssl\openssl\crypto\evp\bio_b64.c	2003-10-29 22:24:10.000000000 +-0200
+++ h:\prj\2intermediate\openssl\openssl\crypto\evp\bio_b64.c	2010-05-01 23:01:50.000000000 +-0200
@@ -61,13 +61,13 @@
 #include "cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/evp.h>
 
 static int b64_write(BIO *h, const char *buf, int num);
 static int b64_read(BIO *h, char *buf, int size);
-/*static int b64_puts(BIO *h, const char *str); */
+static int b64_puts(BIO *h, const char *str);
 /*static int b64_gets(BIO *h, char *str, int size); */
 static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
 static int b64_new(BIO *h);
 static int b64_free(BIO *data);
 static long b64_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp);
 #define B64_BLOCK_SIZE	1024
@@ -93,13 +93,13 @@
 
 static BIO_METHOD methods_b64=
 	{
 	BIO_TYPE_BASE64,"base64 encoding",
 	b64_write,
 	b64_read,
-	NULL, /* b64_puts, */
+	b64_puts,
 	NULL, /* b64_gets, */
 	b64_ctrl,
 	b64_new,
 	b64_free,
 	b64_callback_ctrl,
 	};
@@ -124,12 +124,13 @@
 	ctx->start=1;
 	ctx->encode=0;
 
 	bi->init=1;
 	bi->ptr=(char *)ctx;
 	bi->flags=0;
+	bi->num = 0;
 	return(1);
 	}
 
 static int b64_free(BIO *a)
 	{
 	if (a == NULL) return(0);
@@ -148,24 +149,27 @@
 
 	if (out == NULL) return(0);
 	ctx=(BIO_B64_CTX *)b->ptr;
 
 	if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
 
+	BIO_clear_retry_flags(b);
+
 	if (ctx->encode != B64_DECODE)
 		{
 		ctx->encode=B64_DECODE;
 		ctx->buf_len=0;
 		ctx->buf_off=0;
 		ctx->tmp_len=0;
 		EVP_DecodeInit(&(ctx->base64));
 		}
 
 	/* First check if there are bytes decoded/encoded */
 	if (ctx->buf_len > 0)
 		{
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 		i=ctx->buf_len-ctx->buf_off;
 		if (i > outl) i=outl;
 		OPENSSL_assert(ctx->buf_off+i < (int)sizeof(ctx->buf));
 		memcpy(out,&(ctx->buf[ctx->buf_off]),i);
 		ret=i;
 		out+=i;
@@ -181,24 +185,23 @@
 	/* At this point, we have room of outl bytes and an empty
 	 * buffer, so we should read in some more. */
 
 	ret_code=0;
 	while (outl > 0)
 		{
-
 		if (ctx->cont <= 0)
 			break;
 
 		i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
 			B64_BLOCK_SIZE-ctx->tmp_len);
 
 		if (i <= 0)
 			{
 			ret_code=i;
 
-			/* Should be continue next time we are called? */
+			/* Should we continue next time we are called? */
 			if (!BIO_should_retry(b->next_bio))
 				{
 				ctx->cont=i;
 				/* If buffer empty break */
 				if(ctx->tmp_len == 0)
 					break;
@@ -282,25 +285,33 @@
 					ctx->tmp_len=n;
 					}
 				/* else finished on a '\n' */
 				continue;
 				}
 			else
+			{
 				ctx->tmp_len=0;
 			}
-		/* If buffer isn't full and we can retry then
-		 * restart to read in more data.
-		 */
+		}
 		else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0))
+		{
+			/* If buffer isn't full and we can retry then
+			 * restart to read in more data.
+			 */
 			continue;
+		}
 
 		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
 			{
 			int z,jj;
 
+#if 0
 			jj=(i>>2)<<2;
+#else
+			jj = i & ~3; /* process per 4 */
+#endif
 			z=EVP_DecodeBlock((unsigned char *)ctx->buf,
 				(unsigned char *)ctx->tmp,jj);
 			if (jj > 2)
 				{
 				if (ctx->tmp[jj-1] == '=')
 					{
@@ -310,24 +321,26 @@
 					}
 				}
 			/* z is now number of output bytes and jj is the
 			 * number consumed */
 			if (jj != i)
 				{
+#if 0 /* [i_a] ERROR: some intrinsic memcpy() ops can copy DOWN, thus corrupting the data here */
 				memcpy((unsigned char *)ctx->tmp,
 					(unsigned char *)&(ctx->tmp[jj]),i-jj);
+#else
+					memmove(ctx->tmp, &ctx->tmp[jj], i-jj);
+#endif
 				ctx->tmp_len=i-jj;
 				}
 			ctx->buf_len=0;
 			if (z > 0)
 				{
 				ctx->buf_len=z;
-				i=1;
 				}
-			else
-				i=z;
+			i=z;
 			}
 		else
 			{
 			i=EVP_DecodeUpdate(&(ctx->base64),
 				(unsigned char *)ctx->buf,&ctx->buf_len,
 				(unsigned char *)ctx->tmp,i);
@@ -354,20 +367,22 @@
 			ctx->buf_len=0;
 			ctx->buf_off=0;
 			}
 		outl-=i;
 		out+=i;
 		}
-	BIO_clear_retry_flags(b);
+	/* BIO_clear_retry_flags(b); */
 	BIO_copy_next_retry(b);
 	return((ret == 0)?ret_code:ret);
 	}
 
 static int b64_write(BIO *b, const char *in, int inl)
 	{
-	int ret=inl,n,i;
+	int ret=0; /* [i_a] ERROR: (int)inl; will cause race condition for nonblock bio returning retry code to us below */
+	int n;
+	int i;
 	BIO_B64_CTX *ctx;
 
 	ctx=(BIO_B64_CTX *)b->ptr;
 	BIO_clear_retry_flags(b);
 
 	if (ctx->encode != B64_ENCODE)
@@ -376,22 +391,32 @@
 		ctx->buf_len=0;
 		ctx->buf_off=0;
 		ctx->tmp_len=0;
 		EVP_EncodeInit(&(ctx->base64));
 		}
 
+	/* [i_a] patch by Kai-Min Sung: patch to use CRLF in base64 BIO @ 2004-07-25 */
+	if (BIO_get_flags(b) & BIO_FLAGS_BASE64_CRLF)
+		ctx->base64.crlf_eol=1;
+
+	OPENSSL_assert(ctx->buf_off < sizeof(ctx->buf));
+	OPENSSL_assert(ctx->buf_len <= sizeof(ctx->buf));
+	OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 	n=ctx->buf_len-ctx->buf_off;
 	while (n > 0)
 		{
 		i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
 		if (i <= 0)
 			{
 			BIO_copy_next_retry(b);
 			return(i);
 			}
+		OPENSSL_assert(i <= n);
 		ctx->buf_off+=i;
+		OPENSSL_assert(ctx->buf_off <= sizeof(ctx->buf));
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 		n-=i;
 		}
 	/* at this point all pending data has been written */
 	ctx->buf_off=0;
 	ctx->buf_len=0;
 
@@ -402,47 +427,53 @@
 		n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl;
 
 		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
 			{
 			if (ctx->tmp_len > 0)
 				{
+				OPENSSL_assert(ctx->tmp_len <= 3);
 				n=3-ctx->tmp_len;
-				/* There's a teoretical possibility for this */
+				/* There's a theoretical possibility for this */
 				if (n > inl) 
 					n=inl;
 				memcpy(&(ctx->tmp[ctx->tmp_len]),in,n);
 				ctx->tmp_len+=n;
+				ret += n;
 				if (ctx->tmp_len < 3)
 					break;
-				ctx->buf_len=EVP_EncodeBlock(
-					(unsigned char *)ctx->buf,
-					(unsigned char *)ctx->tmp,
-					ctx->tmp_len);
+				ctx->buf_len=EVP_EncodeBlock(ctx->buf,ctx->tmp,ctx->tmp_len);
+				OPENSSL_assert(ctx->buf_len <= sizeof(ctx->buf));
+				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 				/* Since we're now done using the temporary
 				   buffer, the length should be 0'd */
 				ctx->tmp_len=0;
 				}
 			else
 				{
 				if (n < 3)
 					{
-					memcpy(&(ctx->tmp[0]),in,n);
+					memcpy(ctx->tmp,in,n);
 					ctx->tmp_len=n;
+					ret += n;
 					break;
 					}
 				n-=n%3;
-				ctx->buf_len=EVP_EncodeBlock(
-					(unsigned char *)ctx->buf,
-					(unsigned char *)in,n);
+				ctx->buf_len=EVP_EncodeBlock(ctx->buf,(const unsigned char *)in,n);
+				OPENSSL_assert(ctx->buf_len <= sizeof(ctx->buf));
+				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+				ret += n;
 				}
 			}
 		else
 			{
 			EVP_EncodeUpdate(&(ctx->base64),
 				(unsigned char *)ctx->buf,&ctx->buf_len,
 				(unsigned char *)in,n);
+			OPENSSL_assert(ctx->buf_len <= sizeof(ctx->buf));
+			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+			ret += n;
 			}
 		inl-=n;
 		in+=n;
 
 		ctx->buf_off=0;
 		n=ctx->buf_len;
@@ -451,14 +482,17 @@
 			i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
 			if (i <= 0)
 				{
 				BIO_copy_next_retry(b);
 				return((ret == 0)?i:ret);
 				}
+			OPENSSL_assert(i <= n);
 			n-=i;
 			ctx->buf_off+=i;
+			OPENSSL_assert(ctx->buf_off <= sizeof(ctx->buf));
+			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 			}
 		ctx->buf_len=0;
 		ctx->buf_off=0;
 		}
 	return(ret);
 	}
@@ -483,20 +517,22 @@
 		if (ctx->cont <= 0)
 			ret=1;
 		else
 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
 		break;
 	case BIO_CTRL_WPENDING: /* More to write in buffer */
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 		ret=ctx->buf_len-ctx->buf_off;
 		if ((ret == 0) && (ctx->encode != B64_NONE)
 			&& (ctx->base64.num != 0))
 			ret=1;
 		else if (ret <= 0)
 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
 		break;
 	case BIO_CTRL_PENDING: /* More to read in buffer */
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
 		ret=ctx->buf_len-ctx->buf_off;
 		if (ret <= 0)
 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
 		break;
 	case BIO_CTRL_FLUSH:
 		/* do a final write */
@@ -562,6 +598,14 @@
 		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
 		break;
 		}
 	return(ret);
 	}
 
+static int b64_puts(BIO *b, const char *str)
+	{
+	return b64_write(b,str,strlen(str));
+	}
+
+
+
+
