Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(802)

Unified Diff: third_party/WebKit/Source/core/xml/XPathFunctions.cpp

Issue 2424453002: Handle overflow, underflow in XPath substring position, length. (Closed)
Patch Set: Make windows happy. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/xml/XPathFunctions.cpp
diff --git a/third_party/WebKit/Source/core/xml/XPathFunctions.cpp b/third_party/WebKit/Source/core/xml/XPathFunctions.cpp
index 8fe6c2a563024496d1667ab559ea5a7ff1642203..3daff8125fceb66d020dbdfe64c0083e6c747506 100644
--- a/third_party/WebKit/Source/core/xml/XPathFunctions.cpp
+++ b/third_party/WebKit/Source/core/xml/XPathFunctions.cpp
@@ -37,6 +37,8 @@
#include "wtf/MathExtras.h"
#include "wtf/text/StringBuilder.h"
+#include <limits>
+
namespace blink {
namespace XPath {
@@ -530,34 +532,50 @@ Value FunSubstringAfter::evaluate(EvaluationContext& context) const {
return s1.substring(i + s2.length());
}
-Value FunSubstring::evaluate(EvaluationContext& context) const {
- String s = arg(0)->evaluate(context).toString();
- double doublePos = arg(1)->evaluate(context).toNumber();
- if (std::isnan(doublePos))
- return "";
- long pos = static_cast<long>(FunRound::round(doublePos));
- bool haveLength = argCount() == 3;
- long len = -1;
- if (haveLength) {
- double doubleLen = arg(2)->evaluate(context).toNumber();
- if (std::isnan(doubleLen))
- return "";
- len = static_cast<long>(FunRound::round(doubleLen));
+static unsigned findSubstringStartIndex(unsigned lo, unsigned hi, double pos) {
+ while (lo != hi) {
+ unsigned mid = lo + (hi - lo) / 2;
+ if (mid >= pos)
+ hi = mid;
+ else
+ lo = mid + 1;
yosin_UTC9 2016/10/17 03:56:00 Note: When |pos| is NaN, |mid >= pos| is false. So
dominicc (has gone to gerrit) 2016/10/21 05:28:45 What's wrong with that?
yosin_UTC9 2016/10/21 05:52:03 Sorry for confusion. This is my notes.
}
-
- if (pos > long(s.length()))
- return "";
-
- if (pos < 1) {
- if (haveLength) {
- len -= 1 - pos;
- if (len < 1)
- return "";
- }
- pos = 1;
+ return lo;
+}
+
+// This function may seem redundant given findSubstringStartIndex, but
+// it is different. substring's bounds calculations are designed to
+// work with NaN, and mid >= pos is different to !(mid < pos) when pos
+// is NaN.
+static unsigned findSubstringEndIndex(unsigned lo, unsigned hi, double pos) {
+ while (lo != hi) {
+ unsigned mid = lo + (hi - lo) / 2;
+ if (mid < pos)
+ lo = mid + 1;
+ else
+ hi = mid;
}
+ return lo;
+}
- return s.substring(pos - 1, len);
+// substring(string, number pos, number? len)
+//
+// Characters in string are indexed from 1. Numbers are doubles and
+// substring is specified to work with IEEE-754 infinity, NaN, and
+// XPath's bespoke rounding function, round.
+//
+// <https://www.w3.org/TR/xpath/#function-substring>
+Value FunSubstring::evaluate(EvaluationContext& context) const {
+ String s = arg(0)->evaluate(context).toString();
yosin_UTC9 2016/10/17 03:56:00 nit: It is better to avoid using one letter variab
+ double pos = FunRound::round(arg(1)->evaluate(context).toNumber());
+ double len = argCount() == 3
+ ? FunRound::round(arg(2)->evaluate(context).toNumber())
+ : std::numeric_limits<double>::infinity();
+ unsigned start = findSubstringStartIndex(1, s.length() + 1, pos);
yosin_UTC9 2016/10/17 03:56:00 WDYT? Explicit handling of NaN and Infinity? In th
dominicc (has gone to gerrit) 2016/10/21 05:28:45 I don't think this works. If pos is -inf and end i
yosin_UTC9 2016/10/21 05:52:03 OK. Simpler code is better.
+ unsigned end = findSubstringEndIndex(1, s.length() + 1, pos + len);
+ if (end <= start)
+ return "";
+ return s.substring(start - 1, end - start);
}
Value FunStringLength::evaluate(EvaluationContext& context) const {

Powered by Google App Engine
This is Rietveld 408576698