The bugfix core in the attached diff are these bits:

@@ -351,6 +361,8 @@
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
+                fmtfp(sbuffer, buffer, &currlen, maxlen,
+                      fvalue, min, max, flags); /* [i_a] */
                 break;
             case 'G':
                 flags |= DP_F_UP;
@@ -359,7 +371,41 @@
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
+                fmtfp(sbuffer, buffer, &currlen, maxlen,
+                      fvalue, min, max, flags); /* [i_a] */

^^^ without those fmtfp() calls, you'll never get your %f or %G, etc.
floating point arguments to BIO_printf() et al printed -- up to now,
they were simply silently ignored.

With that comes this additional fix (also in attached diff):

@@ -641,7 +688,7 @@
     /* we "cheat" by converting the fractional part to integer by
        multiplying by a factor of 10 */
     max10 = roundv(pow_10(max));
-    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
+    fracpart = roundv(max10 * (ufvalue - intpart)); /* [i_a] */

     if (fracpart >= max10) {
         intpart++;

which makes sure the fractional part gets calculated correctly, i.e.
shifted by an _integer power of 10_ like it should when you want to
extract particular decimal digits.



The remainder of the patch/diff is a compile-time conditional
alternative for embedded and/or other restricted systems which do not
/ do not want to support floating point printf() support within
OpenSSL. Basically, this is what OpenSSL was doing up to now, though
without the silent skip/ignore of %f,etc. printf() arguments.

Also included are a few assert() --> OPENSSL_assert() fixes.



When you want the 'non-floating point for embedded' code section
(which clearly prints an 'unsupported feature' statement when you try
to print %f, %g, etc. on such a system anyway, which simplifies
problem diagnosis a lot (no silent ignorance), #define that
OPENSSL_NO_FLOAT_SUPPORT in your make environment (I didn't make the
effort to include it as a ./Configure config script option, yet).

>From the accompanying augmented opensslconf.h.in:

-------------
 /* crypto/opensslconf.h.in */

 /* Generate 80386 code? */
 #undef I386_ONLY

+#ifndef OPENSSL_NO_FLOAT_SUPPORT
+/* #define this one if your RTL does not support floating point
printf() formatting options (some embedded OSs / size+feature
reduction) */
+#undef OPENSSL_NO_FLOAT_SUPPORT
+#endif
+
+
----------------


-- 
Met vriendelijke groeten / Best regards,

Ger Hobbelt

--------------------------------------------------
web:    http://www.hobbelt.com/
        http://www.hebbut.net/
mail:   [email protected]
mobile: +31-6-11 120 978
--------------------------------------------------

--- /home/ger/prj/1original/openssl/openssl/./crypto/bio/b_print.c	2007-09-15 19:05:11.000000000 +0200
+++ ./crypto/bio/b_print.c	2008-12-24 20:04:00.000000000 +0100
@@ -70,7 +70,14 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+
+#if 0 /* [i_a] -- changed every assert() to OPENSSL_assert() */
 #include <assert.h>
+#else
+#include <openssl/e_os2.h>
+#include <openssl/crypto.h>
+#endif
+
 #include <limits.h>
 #include "cryptlib.h"
 #ifndef NO_SYS_TYPES_H
@@ -116,7 +123,7 @@
 #endif
 
 #ifdef HAVE_LONG_LONG
-# if defined(_WIN32) && !defined(__GNUC__)
+# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
 # define LLONG __int64
 # else
 # define LLONG long long
@@ -129,8 +136,10 @@
 			const char *, int, int, int);
 static void fmtint     (char **, char **, size_t *, size_t *,
 			LLONG, int, int, int, int);
+#if !defined(OPENSSL_NO_FLOAT_SUPPORT) /* [i_a] */
 static void fmtfp      (char **, char **, size_t *, size_t *,
 			LDOUBLE, int, int, int);
+#endif
 static void doapr_outch (char **, char **, size_t *, size_t *, int);
 static void _dopr(char **sbuffer, char **buffer,
 		  size_t *maxlen, size_t *retlen, int *truncated,
@@ -336,6 +345,7 @@
                        ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
                        min, max, flags);
                 break;
+#if !defined(OPENSSL_NO_FLOAT_SUPPORT) /* [i_a] */
             case 'f':
                 if (cflags == DP_C_LDOUBLE)
                     fvalue = va_arg(args, LDOUBLE);
@@ -351,6 +361,8 @@
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
+                fmtfp(sbuffer, buffer, &currlen, maxlen,
+                      fvalue, min, max, flags); /* [i_a] */
                 break;
             case 'G':
                 flags |= DP_F_UP;
@@ -359,7 +371,41 @@
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
+                fmtfp(sbuffer, buffer, &currlen, maxlen,
+                      fvalue, min, max, flags); /* [i_a] */
+                break;
+#else /* [i_a] */
+				/* no floating point printf() support! */
+            case 'G':
+            case 'g':
+            case 'E':
+            case 'e':
+            case 'f':
+                if (cflags == DP_C_LDOUBLE)
+                    fvalue = va_arg(args, LDOUBLE);
+                else
+                    fvalue = va_arg(args, double);
+                /* popped argument; now print 'we do not support this' string */
+                strvalue = "<no floating point support in printf()>";
+                if (max < 0) 
+                {
+		    		if (buffer)
+						max = INT_MAX;
+		    		else
+						max = *maxlen;
+				}
+				if (max < (int)strlen(strvalue))
+				{
+					strvalue = "NoFP";
+					if (max < (int)strlen(strvalue))
+					{
+						max = strlen(strvalue);
+					}
+				}                            
+                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+                       flags, min, max);
                 break;
+#endif /* [i_a] */
             case 'c':
                 doapr_outch(sbuffer, buffer, &currlen, maxlen,
                     va_arg(args, int));
@@ -597,6 +643,7 @@
     return intpart;
 }
 
+#if !defined(OPENSSL_NO_FLOAT_SUPPORT) /* [i_a] */
 static void
 fmtfp(
     char **sbuffer,
@@ -641,7 +688,7 @@
     /* we "cheat" by converting the fractional part to integer by
        multiplying by a factor of 10 */
     max10 = roundv(pow_10(max));
-    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
+    fracpart = roundv(max10 * (ufvalue - intpart)); /* [i_a] */
 
     if (fracpart >= max10) {
         intpart++;
@@ -721,6 +768,8 @@
         ++padlen;
     }
 }
+#endif /* [i_a] !defined(OPENSSL_NO_FLOAT_SUPPORT) */
+
 
 static void
 doapr_outch(
@@ -730,8 +779,8 @@
     size_t *maxlen,
     int c)
 {
-    /* If we haven't at least one buffer, someone has doe a big booboo */
-    assert(*sbuffer != NULL || buffer != NULL);
+    /* If we haven't at least one buffer, someone has done a big booboo */
+    OPENSSL_assert(*sbuffer != NULL || buffer != NULL);
 
     if (buffer) {
 	while (*currlen >= *maxlen) {
@@ -740,7 +789,7 @@
 		    *maxlen = 1024;
 		*buffer = OPENSSL_malloc(*maxlen);
 		if (*currlen > 0) {
-		    assert(*sbuffer != NULL);
+		    OPENSSL_assert(*sbuffer != NULL);
 		    memcpy(*buffer, *sbuffer, *currlen);
 		}
 		*sbuffer = NULL;
@@ -750,7 +799,7 @@
 	    }
 	}
 	/* What to do if *buffer is NULL? */
-	assert(*sbuffer != NULL || *buffer != NULL);
+	OPENSSL_assert(*sbuffer != NULL || *buffer != NULL);
     }
 
     if (*currlen < *maxlen) {
@@ -840,3 +889,66 @@
 	else
 		return (retlen <= INT_MAX) ? (int)retlen : -1;
 	}
+
+
+/* [i_a] */
+
+/* As asnprintf is not available everywhere, we provide our own implementation.
+ * This function has nothing to do with BIOs, but it's closely related
+ * to BIO_printf, and we need *some* name prefix ...
+ * (XXX  the function should be renamed, but to what?) */
+
+/*
+   Write formatted output to a string dynamically allocated with malloc().
+   You can pass a preallocated buffer for the result in RESULTBUF and its
+   size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+   If successful, return the address of the string (this may be = RESULTBUF
+   if no dynamic memory allocation was necessary) and set *LENGTHP to the
+   number of resulting bytes, excluding the trailing NUL.  Upon error, set
+   errno and return NULL.
+
+   When dynamic memory allocation occurs, the preallocated buffer is left
+   alone (with possibly modified contents).  This makes it possible to use
+   a statically allocated or stack-allocated buffer, like this:
+
+          char buf[100];
+          size_t len = sizeof(buf);
+          char *output = vasnprintf (buf, &len, format, args);
+          if (output == NULL)
+            ... error handling ...;
+          else
+            {
+              ... use the output string ...;
+              if (output != buf)
+                OPENSSL_free(output);
+            }
+  */
+char *BIO_asnprintf(char *buf, size_t *n, const char *format, ...)
+	{
+	va_list args;
+	char *ret;
+
+	va_start(args, format);
+
+	ret = BIO_vasnprintf(buf, n, format, args);
+
+	va_end(args);
+	return(ret);
+	}
+
+char *BIO_vasnprintf(char *buf, size_t *n_ref, const char *format, va_list args)
+	{
+	size_t retlen;
+	char *dynbuf = NULL;
+	int ignored;
+
+	CRYPTO_push_info("BIO_vasnprintf()");
+	_dopr(&buf, &dynbuf, n_ref, &retlen, &ignored, format, args);
+	if (!dynbuf)
+		{
+		dynbuf = buf;
+		}
+	*n_ref = retlen;
+	CRYPTO_pop_info();
+	return dynbuf;
+	}

Reply via email to