This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] gas: bad output of double pseudo instruction


Some numbers are interpreted in bad way by function atof_general.
The next POC is shown:

$ cat << EOF | as -o test -- && objdump -s test
  .data
  .double .0000000000000000000001
  .double 1e-22
EOF

The output is:

test:     file format elf64-x86-64

Contents of section .data:
 0000 00000000 00000000 e65e1710 20395e3b  .........^.. 9^;

Where we note that the same number is interpreted different,
in this case the output of the first form is bad.

The reason of this bug is the function atof_general which assumes,
when the number of digits is calculated, that the ``left'' zeros are
deleted, but this is not the case for the zeros after decimal mark.

The next patch fix this problem by skipping all zeros at the ``left'' side,
when there is zero after decimal mark then they are skipped and an
appropiate decimal_exponent is calculated for the shift which is then
propertly added to the final variable decimal_exponent.
diff --git a/gas/atof-generic.c b/gas/atof-generic.c
index 40ee910c72..0e97dc387c 100644
--- a/gas/atof-generic.c
+++ b/gas/atof-generic.c
@@ -189,18 +189,40 @@ atof_generic (/* return pointer to just AFTER number we read.  */
    * come out inexact for some reason related to length of the digit
    * string.
    */
+  /* The case number_of_digits_before_decimal = 0 is handled for
+   * deleting zeros after decimal. In this case the decimal mark and
+   * the first zero digits after decimal mark are skipped.
+   */
+  seen_significant_digit = 0;
+  long substract_decimal_exponent = 0;
   if (c && IS_DECIMAL_MARK (c))
     {
       unsigned int zeros = 0;	/* Length of current string of zeros */
 
+      if( number_of_digits_before_decimal==0 )
+      {
+          /* skip decimal mark */
+          first_digit++;
+      }
+
       for (p++; (c = *p) && ISDIGIT (c); p++)
 	{
 	  if (c == '0')
 	    {
-	      zeros++;
+          if( number_of_digits_before_decimal == 0 && !seen_significant_digit )
+          {
+              /* skip '0' and */
+              first_digit++;
+              substract_decimal_exponent--;
+          }
+          else
+          {
+            zeros++;
+          }
 	    }
 	  else
 	    {
+          seen_significant_digit=1;
 	      number_of_digits_after_decimal += 1 + zeros;
 	      zeros = 0;
 	    }
@@ -287,6 +309,11 @@ atof_generic (/* return pointer to just AFTER number we read.  */
 	}
     }
 
+  /* substract_decimal_exponent != 0 when number_of_digits_before_decimal = 0
+   * and first digit after decimal is '0'
+   */
+  decimal_exponent += substract_decimal_exponent;
+
   *address_of_string_pointer = p;
 
   number_of_digits_available =

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]