Bugfix: internationalization routines fail on monkeypatching.

Calls to Object.defineProperty() and Object.apply() are not safe.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/253903003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21071 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ae2e32f8
...@@ -258,7 +258,7 @@ function addBoundMethod(obj, methodName, implementation, length) { ...@@ -258,7 +258,7 @@ function addBoundMethod(obj, methodName, implementation, length) {
%FunctionRemovePrototype(getter); %FunctionRemovePrototype(getter);
%SetNativeFlag(getter); %SetNativeFlag(getter);
$Object.defineProperty(obj.prototype, methodName, { ObjectDefineProperty(obj.prototype, methodName, {
get: getter, get: getter,
enumerable: false, enumerable: false,
configurable: true configurable: true
...@@ -593,15 +593,14 @@ function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) { ...@@ -593,15 +593,14 @@ function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) {
*/ */
function freezeArray(array) { function freezeArray(array) {
array.forEach(function(element, index) { array.forEach(function(element, index) {
$Object.defineProperty(array, index, {value: element, ObjectDefineProperty(array, index, {value: element,
configurable: false, configurable: false,
writable: false, writable: false,
enumerable: true}); enumerable: true});
}); });
$Object.defineProperty(array, 'length', {value: array.length, ObjectDefineProperty(array, 'length', {value: array.length,
writable: false}); writable: false});
return array; return array;
} }
...@@ -662,8 +661,8 @@ function getAvailableLocalesOf(service) { ...@@ -662,8 +661,8 @@ function getAvailableLocalesOf(service) {
* Configurable is false by default. * Configurable is false by default.
*/ */
function defineWEProperty(object, property, value) { function defineWEProperty(object, property, value) {
$Object.defineProperty(object, property, ObjectDefineProperty(object, property,
{value: value, writable: true, enumerable: true}); {value: value, writable: true, enumerable: true});
} }
...@@ -682,11 +681,11 @@ function addWEPropertyIfDefined(object, property, value) { ...@@ -682,11 +681,11 @@ function addWEPropertyIfDefined(object, property, value) {
* Defines a property and sets writable, enumerable and configurable to true. * Defines a property and sets writable, enumerable and configurable to true.
*/ */
function defineWECProperty(object, property, value) { function defineWECProperty(object, property, value) {
$Object.defineProperty(object, property, ObjectDefineProperty(object, property,
{value: value, {value: value,
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
} }
...@@ -925,8 +924,8 @@ function initializeCollator(collator, locales, options) { ...@@ -925,8 +924,8 @@ function initializeCollator(collator, locales, options) {
// We define all properties C++ code may produce, to prevent security // We define all properties C++ code may produce, to prevent security
// problems. If malicious user decides to redefine Object.prototype.locale // problems. If malicious user decides to redefine Object.prototype.locale
// we can't just use plain x.locale = 'us' or in C++ Set("locale", "us"). // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us").
// Object.defineProperties will either succeed defining or throw an error. // ObjectDefineProperties will either succeed defining or throw an error.
var resolved = $Object.defineProperties({}, { var resolved = ObjectDefineProperties({}, {
caseFirst: {writable: true}, caseFirst: {writable: true},
collation: {value: internalOptions.collation, writable: true}, collation: {value: internalOptions.collation, writable: true},
ignorePunctuation: {writable: true}, ignorePunctuation: {writable: true},
...@@ -944,7 +943,7 @@ function initializeCollator(collator, locales, options) { ...@@ -944,7 +943,7 @@ function initializeCollator(collator, locales, options) {
// Writable, configurable and enumerable are set to false by default. // Writable, configurable and enumerable are set to false by default.
%MarkAsInitializedIntlObjectOfType(collator, 'collator', internalCollator); %MarkAsInitializedIntlObjectOfType(collator, 'collator', internalCollator);
$Object.defineProperty(collator, 'resolved', {value: resolved}); ObjectDefineProperty(collator, 'resolved', {value: resolved});
return collator; return collator;
} }
...@@ -1141,7 +1140,7 @@ function initializeNumberFormat(numberFormat, locales, options) { ...@@ -1141,7 +1140,7 @@ function initializeNumberFormat(numberFormat, locales, options) {
getOption, internalOptions); getOption, internalOptions);
var requestedLocale = locale.locale + extension; var requestedLocale = locale.locale + extension;
var resolved = $Object.defineProperties({}, { var resolved = ObjectDefineProperties({}, {
currency: {writable: true}, currency: {writable: true},
currencyDisplay: {writable: true}, currencyDisplay: {writable: true},
locale: {writable: true}, locale: {writable: true},
...@@ -1166,12 +1165,12 @@ function initializeNumberFormat(numberFormat, locales, options) { ...@@ -1166,12 +1165,12 @@ function initializeNumberFormat(numberFormat, locales, options) {
// We can't get information about number or currency style from ICU, so we // We can't get information about number or currency style from ICU, so we
// assume user request was fulfilled. // assume user request was fulfilled.
if (internalOptions.style === 'currency') { if (internalOptions.style === 'currency') {
$Object.defineProperty(resolved, 'currencyDisplay', {value: currencyDisplay, ObjectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay,
writable: true}); writable: true});
} }
%MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat', formatter); %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat', formatter);
$Object.defineProperty(numberFormat, 'resolved', {value: resolved}); ObjectDefineProperty(numberFormat, 'resolved', {value: resolved});
return numberFormat; return numberFormat;
} }
...@@ -1443,13 +1442,11 @@ function appendToDateTimeObject(options, option, match, pairs) { ...@@ -1443,13 +1442,11 @@ function appendToDateTimeObject(options, option, match, pairs) {
*/ */
function toDateTimeOptions(options, required, defaults) { function toDateTimeOptions(options, required, defaults) {
if (options === undefined) { if (options === undefined) {
options = null; options = {};
} else { } else {
options = toObject(options); options = TO_OBJECT_INLINE(options);
} }
options = $Object.apply(this, [options]);
var needsDefault = true; var needsDefault = true;
if ((required === 'date' || required === 'any') && if ((required === 'date' || required === 'any') &&
(options.weekday !== undefined || options.year !== undefined || (options.weekday !== undefined || options.year !== undefined ||
...@@ -1464,30 +1461,30 @@ function toDateTimeOptions(options, required, defaults) { ...@@ -1464,30 +1461,30 @@ function toDateTimeOptions(options, required, defaults) {
} }
if (needsDefault && (defaults === 'date' || defaults === 'all')) { if (needsDefault && (defaults === 'date' || defaults === 'all')) {
$Object.defineProperty(options, 'year', {value: 'numeric', ObjectDefineProperty(options, 'year', {value: 'numeric',
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
$Object.defineProperty(options, 'month', {value: 'numeric', ObjectDefineProperty(options, 'month', {value: 'numeric',
writable: true,
enumerable: true,
configurable: true});
$Object.defineProperty(options, 'day', {value: 'numeric',
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
ObjectDefineProperty(options, 'day', {value: 'numeric',
writable: true,
enumerable: true,
configurable: true});
} }
if (needsDefault && (defaults === 'time' || defaults === 'all')) { if (needsDefault && (defaults === 'time' || defaults === 'all')) {
$Object.defineProperty(options, 'hour', {value: 'numeric', ObjectDefineProperty(options, 'hour', {value: 'numeric',
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
$Object.defineProperty(options, 'minute', {value: 'numeric', ObjectDefineProperty(options, 'minute', {value: 'numeric',
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
$Object.defineProperty(options, 'second', {value: 'numeric', ObjectDefineProperty(options, 'second', {value: 'numeric',
writable: true, writable: true,
enumerable: true, enumerable: true,
configurable: true}); configurable: true});
...@@ -1538,7 +1535,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) { ...@@ -1538,7 +1535,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
getOption, internalOptions); getOption, internalOptions);
var requestedLocale = locale.locale + extension; var requestedLocale = locale.locale + extension;
var resolved = $Object.defineProperties({}, { var resolved = ObjectDefineProperties({}, {
calendar: {writable: true}, calendar: {writable: true},
day: {writable: true}, day: {writable: true},
era: {writable: true}, era: {writable: true},
...@@ -1566,7 +1563,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) { ...@@ -1566,7 +1563,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
} }
%MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter); %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter);
$Object.defineProperty(dateFormat, 'resolved', {value: resolved}); ObjectDefineProperty(dateFormat, 'resolved', {value: resolved});
return dateFormat; return dateFormat;
} }
...@@ -1760,7 +1757,7 @@ function initializeBreakIterator(iterator, locales, options) { ...@@ -1760,7 +1757,7 @@ function initializeBreakIterator(iterator, locales, options) {
'type', 'string', ['character', 'word', 'sentence', 'line'], 'word')); 'type', 'string', ['character', 'word', 'sentence', 'line'], 'word'));
var locale = resolveLocale('breakiterator', locales, options); var locale = resolveLocale('breakiterator', locales, options);
var resolved = $Object.defineProperties({}, { var resolved = ObjectDefineProperties({}, {
requestedLocale: {value: locale.locale, writable: true}, requestedLocale: {value: locale.locale, writable: true},
type: {value: internalOptions.type, writable: true}, type: {value: internalOptions.type, writable: true},
locale: {writable: true} locale: {writable: true}
...@@ -1772,7 +1769,7 @@ function initializeBreakIterator(iterator, locales, options) { ...@@ -1772,7 +1769,7 @@ function initializeBreakIterator(iterator, locales, options) {
%MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator', %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator',
internalIterator); internalIterator);
$Object.defineProperty(iterator, 'resolved', {value: resolved}); ObjectDefineProperty(iterator, 'resolved', {value: resolved});
return iterator; return iterator;
} }
...@@ -1938,7 +1935,7 @@ function cachedOrNewService(service, locales, options, defaults) { ...@@ -1938,7 +1935,7 @@ function cachedOrNewService(service, locales, options, defaults) {
* Compares this and that, and returns less than 0, 0 or greater than 0 value. * Compares this and that, and returns less than 0, 0 or greater than 0 value.
* Overrides the built-in method. * Overrides the built-in method.
*/ */
$Object.defineProperty($String.prototype, 'localeCompare', { ObjectDefineProperty($String.prototype, 'localeCompare', {
value: function(that) { value: function(that) {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
...@@ -1969,7 +1966,7 @@ $Object.defineProperty($String.prototype, 'localeCompare', { ...@@ -1969,7 +1966,7 @@ $Object.defineProperty($String.prototype, 'localeCompare', {
* If the form is not one of "NFC", "NFD", "NFKC", or "NFKD", then throw * If the form is not one of "NFC", "NFD", "NFKC", or "NFKD", then throw
* a RangeError Exception. * a RangeError Exception.
*/ */
$Object.defineProperty($String.prototype, 'normalize', { ObjectDefineProperty($String.prototype, 'normalize', {
value: function(that) { value: function(that) {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
...@@ -2000,7 +1997,7 @@ $Object.defineProperty($String.prototype, 'normalize', { ...@@ -2000,7 +1997,7 @@ $Object.defineProperty($String.prototype, 'normalize', {
* Formats a Number object (this) using locale and options values. * Formats a Number object (this) using locale and options values.
* If locale or options are omitted, defaults are used. * If locale or options are omitted, defaults are used.
*/ */
$Object.defineProperty($Number.prototype, 'toLocaleString', { ObjectDefineProperty($Number.prototype, 'toLocaleString', {
value: function() { value: function() {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
...@@ -2050,7 +2047,7 @@ function toLocaleDateTime(date, locales, options, required, defaults, service) { ...@@ -2050,7 +2047,7 @@ function toLocaleDateTime(date, locales, options, required, defaults, service) {
* If locale or options are omitted, defaults are used - both date and time are * If locale or options are omitted, defaults are used - both date and time are
* present in the output. * present in the output.
*/ */
$Object.defineProperty($Date.prototype, 'toLocaleString', { ObjectDefineProperty($Date.prototype, 'toLocaleString', {
value: function() { value: function() {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
...@@ -2075,7 +2072,7 @@ $Object.defineProperty($Date.prototype, 'toLocaleString', { ...@@ -2075,7 +2072,7 @@ $Object.defineProperty($Date.prototype, 'toLocaleString', {
* If locale or options are omitted, defaults are used - only date is present * If locale or options are omitted, defaults are used - only date is present
* in the output. * in the output.
*/ */
$Object.defineProperty($Date.prototype, 'toLocaleDateString', { ObjectDefineProperty($Date.prototype, 'toLocaleDateString', {
value: function() { value: function() {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
...@@ -2100,7 +2097,7 @@ $Object.defineProperty($Date.prototype, 'toLocaleDateString', { ...@@ -2100,7 +2097,7 @@ $Object.defineProperty($Date.prototype, 'toLocaleDateString', {
* If locale or options are omitted, defaults are used - only time is present * If locale or options are omitted, defaults are used - only time is present
* in the output. * in the output.
*/ */
$Object.defineProperty($Date.prototype, 'toLocaleTimeString', { ObjectDefineProperty($Date.prototype, 'toLocaleTimeString', {
value: function() { value: function() {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
......
// Copyright 2014 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.
function overflow() {
return overflow() + 1;
}
Object.defineProperty = overflow;
assertDoesNotThrow(function() { Intl.Collator.supportedLocalesOf("en"); });
var date = new Date(Date.UTC(2004, 12, 25, 3, 0, 0));
var options = {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
};
Object.apply = overflow;
assertDoesNotThrow(function() { date.toLocaleDateString("de-DE", options); });
var options_incomplete = {};
assertDoesNotThrow(function() {
date.toLocaleDateString("de-DE", options_incomplete);
});
assertTrue(options_incomplete.hasOwnProperty("year"));
assertDoesNotThrow(function() { date.toLocaleDateString("de-DE", undefined); });
assertDoesNotThrow(function() { date.toLocaleDateString("de-DE"); });
assertThrows(function() { date.toLocaleDateString("de-DE", null); }, TypeError);
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