Commit 5562cfac authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Base64 bio fixes. The base64 bio was seriously broken

when reading from a non blocking BIO.

It would incorrectly interpret retries as EOF, incorrectly
buffer initial data and have no buffering at all after initial
data (data would be sent one byte at a time to EVP_DecodeUpdate).
parent c8252b71
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -4,6 +4,11 @@

 Changes between 0.9.7a and 0.9.8  [xx XXX xxxx]

  *) Various fixes to base64 BIO and non blocking I/O. On write 
     flushes were not handled properly if the BIO retried. On read
     data was not being buffered properly and had various logic bugs.
     [Steve Henson]

  *) Support for single pass processing for S/MIME signing. This now
     means that S/MIME signing can be done from a pipe, in addition
     cleartext signing (multipart/signed type) is effectively streaming
+27 −6
Original line number Diff line number Diff line
@@ -184,7 +184,9 @@ static int b64_read(BIO *b, char *out, int outl)
	ret_code=0;
	while (outl > 0)
		{
		if (ctx->cont <= 0) break;

		if (ctx->cont <= 0)
			break;

		i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
			B64_BLOCK_SIZE-ctx->tmp_len);
@@ -195,11 +197,21 @@ static int b64_read(BIO *b, char *out, int outl)

			/* Should be continue next time we are called? */
			if (!BIO_should_retry(b->next_bio))
				{
				ctx->cont=i;
			/* else we should continue when called again */
				/* If buffer empty break */
				if(ctx->tmp_len == 0)
					break;
				/* Fall through and process what we have */
				else
					i = 0;
				}
			/* else we retry and add more data to buffer */
			else
				break;
			}
		i+=ctx->tmp_len;
		ctx->tmp_len = i;

		/* We need to scan, a line at a time until we
		 * have a valid line if we are starting. */
@@ -254,10 +266,14 @@ static int b64_read(BIO *b, char *out, int outl)
				/* Is this is one long chunk?, if so, keep on
				 * reading until a new line. */
				if (p == (unsigned char *)&(ctx->tmp[0]))
					{
					/* Check buffer full */
					if (i == B64_BLOCK_SIZE)
						{
						ctx->tmp_nl=1;
						ctx->tmp_len=0;
						}
					}
				else if (p != q) /* finished on a '\n' */
					{
					n=q-p;
@@ -271,6 +287,11 @@ static int b64_read(BIO *b, char *out, int outl)
			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))
			continue;

		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
			{
@@ -310,8 +331,8 @@ static int b64_read(BIO *b, char *out, int outl)
			i=EVP_DecodeUpdate(&(ctx->base64),
				(unsigned char *)ctx->buf,&ctx->buf_len,
				(unsigned char *)ctx->tmp,i);
			ctx->tmp_len = 0;
			}
		ctx->cont=i;
		ctx->buf_off=0;
		if (i < 0)
			{