Commit 831bc233 authored by Jungshik Shin's avatar Jungshik Shin Committed by Commit Bot

Intl.DateTimeFormat: throw RangeError for non-finite input

intl.js throws an exception when datetime-value to format is
Infinity or NaN, but there was a way to thwart the check.

Moreover, intl.js and runtime-intl.cc have unnecessary conversions
of 'Number->Date->Number'. I removed the unnecessary conversion
and made 'Number' be passed to %InternalDateFormat.  With this
streamlining, the work-around mentioned above does not work
anymore.

Add a check in runtime_intl.cc for Infinity/NaN and throw a
RangeError.

Add invalid-time test for invalid datetime-values passed to
Intl.DateTimeFormat.format().

Bug: chromium:774833
Test: intl/date-format/invalid-time.js
Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng
Change-Id: Idc575e532a86ee110dc4bb945ae023d6516650ee
Reviewed-on: https://chromium-review.googlesource.com/724860
Commit-Queue: Jungshik Shin <jshin@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48765}
parent 3e4a720b
......@@ -1804,9 +1804,7 @@ function formatDate(formatter, dateValue) {
dateMs = TO_NUMBER(dateValue);
}
if (!NUMBER_IS_FINITE(dateMs)) throw %make_range_error(kDateRange);
return %InternalDateFormat(formatter, new GlobalDate(dateMs));
return %InternalDateFormat(formatter, dateMs);
}
DEFINE_METHOD(
......@@ -1828,9 +1826,7 @@ DEFINE_METHOD(
dateMs = TO_NUMBER(dateValue);
}
if (!NUMBER_IS_FINITE(dateMs)) throw %make_range_error(kDateRange);
return %InternalDateFormatToParts(this, new GlobalDate(dateMs));
return %InternalDateFormatToParts(this, dateMs);
}
);
......
......@@ -8,6 +8,7 @@
#include "src/runtime/runtime-utils.h"
#include <cmath>
#include <memory>
#include "src/api-natives.h"
......@@ -260,17 +261,21 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(date, 1);
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
double date_value = date->Number();
// Check for +-Infinity and Nan
if (!std::isfinite(date_value)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
}
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
CHECK_NOT_NULL(date_format);
icu::UnicodeString result;
date_format->format(value->Number(), result);
date_format->format(date_value, result);
RETURN_RESULT_OR_FAILURE(
isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
......@@ -362,10 +367,13 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormatToParts) {
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(date, 1);
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
double date_value = date->Number();
if (!std::isfinite(date_value)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
}
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
......@@ -375,7 +383,7 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormatToParts) {
icu::FieldPositionIterator fp_iter;
icu::FieldPosition fp;
UErrorCode status = U_ZERO_ERROR;
date_format->format(value->Number(), formatted, &fp_iter, status);
date_format->format(date_value, formatted, &fp_iter, status);
if (U_FAILURE(status)) return isolate->heap()->undefined_value();
Handle<JSArray> result = factory->NewJSArray(0);
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var df = new Intl.DateTimeFormat();
assertThrows("df.format(Infinity)", RangeError);
assertThrows("df.formatToParts(Infinity)", RangeError);
assertThrows("df.format(-Infinity)", RangeError);
assertThrows("df.formatToParts(-Infinity)", RangeError);
assertThrows("df.format(NaN)", RangeError);
assertThrows("df.formatToParts(NaN)", RangeError);
// https://crbug.com/774833
var df2 = new Intl.DateTimeFormat('en', {'hour': 'numeric'});
Date.prototype.valueOf = "ponies";
assertEquals(df.format(Date.now()), df.format());
assertEquals(df2.format(Date.now()), df2.format());
assertEquals(df.formatToParts(Date.now()), df.formatToParts());
assertEquals(df2.formatToParts(Date.now()), df2.formatToParts());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment