[libxml2] Parse small XPath numbers more accurately
- From: Nick Wellnhofer <nwellnhof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml2] Parse small XPath numbers more accurately
- Date: Thu, 1 Jun 2017 13:01:48 +0000 (UTC)
commit a851868a75c108e3b8fc507f5d6555b09abb51c9
Author: Nick Wellnhofer <wellnhofer aevum de>
Date: Mon May 29 20:14:42 2017 +0200
Parse small XPath numbers more accurately
Don't count leading zeros towards the fraction size limit. This allows
to parse numbers like
0.0000000000000000000000000000000000000000000000000000000001
which is the only standard-conformant way to represent such numbers, as
scientific notation isn't allowed in XPath 1.0. (It is allowed in XPath
2.0 and in libxml2 as an extension, though.)
Overall accuracy is still bad, see bug 783238.
result/XPath/expr/base | 8 ++++++++
test/XPath/expr/base | 2 ++
xpath.c | 36 ++++++++++++++++--------------------
3 files changed, 26 insertions(+), 20 deletions(-)
---
diff --git a/result/XPath/expr/base b/result/XPath/expr/base
index e04346f..e2f6389 100644
--- a/result/XPath/expr/base
+++ b/result/XPath/expr/base
@@ -24,5 +24,13 @@ Expression: 1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+
Object is a number : 21
========================
+Expression: 0.000000000000000000000000000000000000000000000000001
+Object is a number : 1e-51
+
+========================
+Expression: -0.000000000000000000000000000000000000000000000000001
+Object is a number : -1e-51
+
+========================
Expression: self::-name
Object is empty (NULL)
diff --git a/test/XPath/expr/base b/test/XPath/expr/base
index f57e4d0..823f64b 100644
--- a/test/XPath/expr/base
+++ b/test/XPath/expr/base
@@ -4,4 +4,6 @@
1+2*3+4
(1+2)*(3+4)
1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1+1*1
+0.000000000000000000000000000000000000000000000000001
+-0.000000000000000000000000000000000000000000000000001
self::-name
diff --git a/xpath.c b/xpath.c
index 0a24be6..d40bdda 100644
--- a/xpath.c
+++ b/xpath.c
@@ -10056,20 +10056,6 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
#define MAX_FRAC 20
-/*
- * These are used as divisors for the fractional part of a number.
- * Since the table includes 1.0 (representing '0' fractional digits),
- * it must be dimensioned at MAX_FRAC+1 (bug 133921)
- */
-static double my_pow10[MAX_FRAC+1] = {
- 1.0, 10.0, 100.0, 1000.0, 10000.0,
- 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
- 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
- 100000000000000.0,
- 1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
- 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0
-};
-
/**
* xmlXPathStringEvalNumber:
* @str: A string to scan
@@ -10132,20 +10118,25 @@ xmlXPathStringEvalNumber(const xmlChar *str) {
#endif
if (*cur == '.') {
- int v, frac = 0;
+ int v, frac = 0, max;
double fraction = 0;
cur++;
if (((*cur < '0') || (*cur > '9')) && (!ok)) {
return(xmlXPathNAN);
}
- while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
+ while (*cur == '0') {
+ frac = frac + 1;
+ cur++;
+ }
+ max = frac + MAX_FRAC;
+ while (((*cur >= '0') && (*cur <= '9')) && (frac < max)) {
v = (*cur - '0');
fraction = fraction * 10 + v;
frac = frac + 1;
cur++;
}
- fraction /= my_pow10[frac];
+ fraction /= pow(10.0, frac);
ret = ret + fraction;
while ((*cur >= '0') && (*cur <= '9'))
cur++;
@@ -10221,20 +10212,25 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
}
#endif
if (CUR == '.') {
- int v, frac = 0;
+ int v, frac = 0, max;
double fraction = 0;
NEXT;
if (((CUR < '0') || (CUR > '9')) && (!ok)) {
XP_ERROR(XPATH_NUMBER_ERROR);
}
- while ((CUR >= '0') && (CUR <= '9') && (frac < MAX_FRAC)) {
+ while (CUR == '0') {
+ frac = frac + 1;
+ NEXT;
+ }
+ max = frac + MAX_FRAC;
+ while ((CUR >= '0') && (CUR <= '9') && (frac < max)) {
v = (CUR - '0');
fraction = fraction * 10 + v;
frac = frac + 1;
NEXT;
}
- fraction /= my_pow10[frac];
+ fraction /= pow(10.0, frac);
ret = ret + fraction;
while ((CUR >= '0') && (CUR <= '9'))
NEXT;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]