commit 2dc49d1: [Fix] Fix some more corner cases for fpconv

Vsevolod Stakhov vsevolod at highsecure.ru
Sun May 19 19:35:03 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-05-19 10:35:34 +0100
URL: https://github.com/rspamd/rspamd/commit/2dc49d136538276625a38d0944d221a1f0580d54

[Fix] Fix some more corner cases for fpconv

---
 contrib/fpconv/fpconv.c | 46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/contrib/fpconv/fpconv.c b/contrib/fpconv/fpconv.c
index 4ec2e3560..3b96af270 100644
--- a/contrib/fpconv/fpconv.c
+++ b/contrib/fpconv/fpconv.c
@@ -236,26 +236,24 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg,
             	return ndigits + 2 + offset;
             }
             else {
-            	/* Overflow */
-            	dest[2] = '0';
-            	return 3;
+            	goto scientific_fallback;
             }
 
         /* fp > 1.0 */
         } else {
-            memcpy(dest, digits, offset);
-
             /* Overflow check */
             if (ndigits <= 23) {
+            	memcpy(dest, digits, offset);
             	dest[offset] = '.';
             	memcpy(dest + offset + 1, digits + offset, ndigits - offset);
             	return ndigits + 1;
             }
 
-            return offset;
+            goto scientific_fallback;
         }
     }
 
+scientific_fallback:
     /* write decimal w/ scientific notation */
     ndigits = minv(ndigits, 18 - neg);
 
@@ -296,9 +294,18 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg,
 
 static int filter_special(double fp, char* dest)
 {
+	int nchars = 3;
+
     if(fp == 0.0) {
-        dest[0] = '0';
-        return 1;
+		if(get_dbits(fp) & signmask) {
+			dest[0] = '-';
+			dest[1] = '0';
+			return 2;
+		}
+		else {
+			dest[0] = '0';
+			return 1;
+		}
     }
 
     uint64_t bits = get_dbits(fp);
@@ -311,12 +318,18 @@ static int filter_special(double fp, char* dest)
 
     if(bits & fracmask) {
         dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
-
     } else {
-        dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+		if(get_dbits(fp) & signmask) {
+			dest[0] = '-';
+			dest[1] = 'i'; dest[2] = 'n'; dest[3] = 'f';
+			nchars = 4;
+		}
+		else {
+			dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+		}
     }
 
-    return 3;
+    return nchars;
 }
 
 int fpconv_dtoa(double d, char dest[24], bool scientific)
@@ -326,11 +339,6 @@ int fpconv_dtoa(double d, char dest[24], bool scientific)
     int str_len = 0;
     bool neg = false;
 
-    if(get_dbits(d) & signmask) {
-        dest[0] = '-';
-        str_len++;
-        neg = true;
-    }
 
     int spec = filter_special(d, dest + str_len);
 
@@ -338,6 +346,12 @@ int fpconv_dtoa(double d, char dest[24], bool scientific)
         return str_len + spec;
     }
 
+	if(get_dbits(d) & signmask) {
+		dest[0] = '-';
+		str_len++;
+		neg = true;
+	}
+
     int K = 0;
     int ndigits = grisu2(d, digits, &K);
 


More information about the Commits mailing list