#947050 libxml2: string() is buggy on floating-point values

Package:
libxml2
Source:
libxml2
Description:
GNOME XML library
Submitter:
Vincent Lefevre
Date:
2021-07-07 10:39:04 UTC
Severity:
important
Tags:
#947050#5
Date:
2019-12-20 02:04:19 UTC
From:
To:
Parsing floating-point numbers give incorrect values:

$ echo '<a/>' | xmllint --xpath "string(1.0999999999999999)" - ; echo
1.1

This is incorrect because of the following.

$ echo '<a/>' | xmllint --xpath "string(1.1)" - ; echo
1.1

Since they produce the same output, this would mean that
1.0999999999999999 and 1.1 correspond to the same double-precision
value. But this is not the case:

$ echo '<a/>' | xmllint --xpath "string(1.1 - 1.0999999999999999)" - ; echo
2.22044604925031e-16

This shows that 1.0999999999999999 and 1.1 are converted to different
floating-point numbers, which is correct. This can also be checked
with atof() in C:

1.0999999999999999 gives 0x1.1999999999999p+0
1.1                gives 0x1.199999999999ap+0

i.e. 2 different double-precision numbers.

Thus the bug is in the string() function.

I recall the XPath 1.0 spec:

https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions

"otherwise, the number is represented in decimal form as a Number
including a decimal point with at least one digit before the decimal
point and at least one digit after the decimal point, preceded by a
minus sign (-) if the number is negative; there must be no leading
zeros before the decimal point apart possibly from the one required
digit immediately before the decimal point; beyond the one required
digit after the decimal point there must be as many, but only as many,
more digits as are needed to uniquely distinguish the number from all
other IEEE 754 numeric values."

See the last requirement.

Note that the libxml2 version in Debian is very old. I have not
checked the latest upstream version.