@@ -723,7 +723,7 @@ private static Object js_from(Context cx, Scriptable scope, Scriptable thisObj,
723
723
}
724
724
}
725
725
726
- final long length = getLengthProperty (cx , items , false );
726
+ final long length = getLengthProperty (cx , items );
727
727
final Scriptable result = callConstructorOrCreateArray (cx , scope , thisObj , length , true );
728
728
for (long k = 0 ; k < length ; k ++) {
729
729
Object temp = getRawElem (items , k );
@@ -846,7 +846,7 @@ private void setLength(Object val) {
846
846
* getLengthProperty returns 0 if obj does not have the length property
847
847
* or its value is not convertible to a number.
848
848
*/
849
- static long getLengthProperty (Context cx , Scriptable obj , boolean throwIfTooLarge ) {
849
+ static long getLengthProperty (Context cx , Scriptable obj ) {
850
850
// These will both give numeric lengths within Uint32 range.
851
851
if (obj instanceof NativeString ) {
852
852
return ((NativeString )obj ).getLength ();
@@ -862,17 +862,15 @@ static long getLengthProperty(Context cx, Scriptable obj, boolean throwIfTooLarg
862
862
}
863
863
864
864
double doubleLen = ScriptRuntime .toNumber (len );
865
+
866
+ // ToLength
865
867
if (doubleLen > NativeNumber .MAX_SAFE_INTEGER ) {
866
- if (throwIfTooLarge ) {
867
- String msg = ScriptRuntime .getMessageById ("msg.arraylength.bad" );
868
- throw ScriptRuntime .rangeError (msg );
869
- }
870
- return (int ) NativeNumber .MAX_SAFE_INTEGER ;
868
+ return (long ) NativeNumber .MAX_SAFE_INTEGER ;
871
869
}
872
870
if (doubleLen < 0 ) {
873
871
return 0 ;
874
872
}
875
- return ScriptRuntime . toUint32 ( len ) ;
873
+ return ( long ) doubleLen ;
876
874
}
877
875
878
876
private static Object setLengthProperty (Context cx , Scriptable target ,
@@ -949,7 +947,7 @@ private static String toStringHelper(Context cx, Scriptable scope,
949
947
/* It's probably redundant to handle long lengths in this
950
948
* function; StringBuilders are limited to 2^31 in java.
951
949
*/
952
- long length = getLengthProperty (cx , o , false );
950
+ long length = getLengthProperty (cx , o );
953
951
954
952
StringBuilder result = new StringBuilder (256 );
955
953
@@ -1044,7 +1042,7 @@ private static String js_join(Context cx, Scriptable scope, Scriptable thisObj,
1044
1042
{
1045
1043
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1046
1044
1047
- long llength = getLengthProperty (cx , o , false );
1045
+ long llength = getLengthProperty (cx , o );
1048
1046
int length = (int )llength ;
1049
1047
if (llength != length ) {
1050
1048
throw Context .reportRuntimeErrorById (
@@ -1120,7 +1118,7 @@ private static Scriptable js_reverse(Context cx, Scriptable scope, Scriptable th
1120
1118
return o ;
1121
1119
}
1122
1120
}
1123
- long len = getLengthProperty (cx , o , false );
1121
+ long len = getLengthProperty (cx , o );
1124
1122
1125
1123
long half = len / 2 ;
1126
1124
for (long i =0 ; i < half ; i ++) {
@@ -1170,7 +1168,7 @@ public int compare(final Object x, final Object y) {
1170
1168
comparator = DEFAULT_COMPARATOR ;
1171
1169
}
1172
1170
1173
- long llength = getLengthProperty (cx , o , false );
1171
+ long llength = getLengthProperty (cx , o );
1174
1172
final int length = (int ) llength ;
1175
1173
if (llength != length ) {
1176
1174
throw Context .reportRuntimeErrorById (
@@ -1209,7 +1207,7 @@ private static Object js_push(Context cx, Scriptable scope, Scriptable thisObj,
1209
1207
return ScriptRuntime .wrapNumber (na .length );
1210
1208
}
1211
1209
}
1212
- long length = getLengthProperty (cx , o , false );
1210
+ long length = getLengthProperty (cx , o );
1213
1211
for (int i = 0 ; i < args .length ; i ++) {
1214
1212
setElem (cx , o , length + i , args [i ]);
1215
1213
}
@@ -1245,7 +1243,7 @@ private static Object js_pop(Context cx, Scriptable scope, Scriptable thisObj,
1245
1243
return result ;
1246
1244
}
1247
1245
}
1248
- long length = getLengthProperty (cx , o , false );
1246
+ long length = getLengthProperty (cx , o );
1249
1247
if (length > 0 ) {
1250
1248
length --;
1251
1249
@@ -1280,7 +1278,7 @@ private static Object js_shift(Context cx, Scriptable scope, Scriptable thisObj,
1280
1278
}
1281
1279
}
1282
1280
Object result ;
1283
- long length = getLengthProperty (cx , o , false );
1281
+ long length = getLengthProperty (cx , o );
1284
1282
if (length > 0 ) {
1285
1283
long i = 0 ;
1286
1284
length --;
@@ -1326,10 +1324,14 @@ private static Object js_unshift(Context cx, Scriptable scope, Scriptable thisOb
1326
1324
return ScriptRuntime .wrapNumber (na .length );
1327
1325
}
1328
1326
}
1329
- long length = getLengthProperty (cx , o , false );
1327
+ long length = getLengthProperty (cx , o );
1330
1328
int argc = args .length ;
1331
1329
1332
- if (args .length > 0 ) {
1330
+ if (argc > 0 ) {
1331
+ if (length + argc > NativeNumber .MAX_SAFE_INTEGER ) {
1332
+ throw ScriptRuntime .typeErrorById ("msg.arraylength.too.big" , length + argc );
1333
+ }
1334
+
1333
1335
/* Slide up the array to make room for args at the bottom */
1334
1336
if (length > 0 ) {
1335
1337
for (long last = length - 1 ; last >= 0 ; last --) {
@@ -1344,17 +1346,17 @@ private static Object js_unshift(Context cx, Scriptable scope, Scriptable thisOb
1344
1346
}
1345
1347
}
1346
1348
/* Follow Perl by returning the new array length. */
1347
- length += args . length ;
1349
+ length += argc ;
1348
1350
return setLengthProperty (cx , o , length );
1349
1351
}
1350
1352
1351
1353
private static Object js_splice (Context cx , Scriptable scope ,
1352
1354
Scriptable thisObj , Object [] args )
1353
1355
{
1354
- Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1356
+ Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1355
1357
1356
- NativeArray na = null ;
1357
- boolean denseMode = false ;
1358
+ NativeArray na = null ;
1359
+ boolean denseMode = false ;
1358
1360
if (o instanceof NativeArray ) {
1359
1361
na = (NativeArray ) o ;
1360
1362
denseMode = na .denseOnly ;
@@ -1365,34 +1367,43 @@ private static Object js_splice(Context cx, Scriptable scope,
1365
1367
int argc = args .length ;
1366
1368
if (argc == 0 )
1367
1369
return cx .newArray (scope , 0 );
1368
- long length = getLengthProperty (cx , o , false );
1370
+ long length = getLengthProperty (cx , o );
1369
1371
1370
1372
/* Convert the first argument into a starting index. */
1371
1373
long begin = toSliceIndex (ScriptRuntime .toInteger (args [0 ]), length );
1372
1374
argc --;
1373
1375
1374
1376
/* Convert the second argument into count */
1375
- long count ;
1377
+ long actualDeleteCount ;
1376
1378
if (args .length == 1 ) {
1377
- count = length - begin ;
1379
+ actualDeleteCount = length - begin ;
1378
1380
} else {
1379
1381
double dcount = ScriptRuntime .toInteger (args [1 ]);
1380
1382
if (dcount < 0 ) {
1381
- count = 0 ;
1383
+ actualDeleteCount = 0 ;
1382
1384
} else if (dcount > (length - begin )) {
1383
- count = length - begin ;
1385
+ actualDeleteCount = length - begin ;
1384
1386
} else {
1385
- count = (long )dcount ;
1387
+ actualDeleteCount = (long )dcount ;
1386
1388
}
1387
1389
argc --;
1388
1390
}
1389
1391
1390
- long end = begin + count ;
1392
+ long end = begin + actualDeleteCount ;
1393
+ long delta = argc - actualDeleteCount ;
1394
+
1395
+ if (length + delta > NativeNumber .MAX_SAFE_INTEGER ) {
1396
+ throw ScriptRuntime .typeErrorById ("msg.arraylength.too.big" , length + delta );
1397
+ }
1398
+ if (actualDeleteCount > Integer .MAX_VALUE ) {
1399
+ String msg = ScriptRuntime .getMessageById ("msg.arraylength.bad" );
1400
+ throw ScriptRuntime .rangeError (msg );
1401
+ }
1391
1402
1392
1403
/* If there are elements to remove, put them into the return value. */
1393
1404
Object result ;
1394
- if (count != 0 ) {
1395
- if (count == 1
1405
+ if (actualDeleteCount != 0 ) {
1406
+ if (actualDeleteCount == 1
1396
1407
&& (cx .getLanguageVersion () == Context .VERSION_1_2 ))
1397
1408
{
1398
1409
/*
@@ -1426,7 +1437,7 @@ private static Object js_splice(Context cx, Scriptable scope,
1426
1437
result = resultArray ;
1427
1438
}
1428
1439
}
1429
- } else { // (count == 0)
1440
+ } else { // (actualDeleteCount == 0)
1430
1441
if (cx .getLanguageVersion () == Context .VERSION_1_2 ) {
1431
1442
/* Emulate C JS1.2; if no elements are removed, return undefined. */
1432
1443
result = Undefined .instance ;
@@ -1436,7 +1447,6 @@ private static Object js_splice(Context cx, Scriptable scope,
1436
1447
}
1437
1448
1438
1449
/* Find the direction (up or down) to copy and make way for argv. */
1439
- long delta = argc - count ;
1440
1450
if (denseMode && length + delta < Integer .MAX_VALUE &&
1441
1451
na .ensureCapacity ((int ) (length + delta )))
1442
1452
{
@@ -1512,7 +1522,7 @@ private static boolean isConcatSpreadable(Context cx, Scriptable scope, Object v
1512
1522
// dense arrays.
1513
1523
private static long concatSpreadArg (Context cx ,
1514
1524
Scriptable result , Scriptable arg , long offset ) {
1515
- long srclen = getLengthProperty (cx , arg , false );
1525
+ long srclen = getLengthProperty (cx , arg );
1516
1526
long newlen = srclen + offset ;
1517
1527
1518
1528
// First, optimize for a pair of native, dense arrays
@@ -1577,8 +1587,7 @@ private static Scriptable js_slice(Context cx, Scriptable scope, Scriptable this
1577
1587
{
1578
1588
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1579
1589
1580
- Scriptable result = cx .newArray (scope , 0 );
1581
- long len = getLengthProperty (cx , o , false );
1590
+ long len = getLengthProperty (cx , o );
1582
1591
1583
1592
long begin , end ;
1584
1593
if (args .length == 0 ) {
@@ -1593,6 +1602,12 @@ private static Scriptable js_slice(Context cx, Scriptable scope, Scriptable this
1593
1602
}
1594
1603
}
1595
1604
1605
+ if (end - begin > Integer .MAX_VALUE ) {
1606
+ String msg = ScriptRuntime .getMessageById ("msg.arraylength.bad" );
1607
+ throw ScriptRuntime .rangeError (msg );
1608
+ }
1609
+
1610
+ Scriptable result = cx .newArray (scope , 0 );
1596
1611
for (long slot = begin ; slot < end ; slot ++) {
1597
1612
Object temp = getRawElem (o , slot );
1598
1613
if (temp != NOT_FOUND ) {
@@ -1625,7 +1640,7 @@ private static Object js_indexOf(Context cx, Scriptable scope, Scriptable thisOb
1625
1640
Object compareTo = args .length > 0 ? args [0 ] : Undefined .instance ;
1626
1641
1627
1642
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1628
- long length = getLengthProperty (cx , o , false );
1643
+ long length = getLengthProperty (cx , o );
1629
1644
/*
1630
1645
* From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf
1631
1646
* The index at which to begin the search. Defaults to 0, i.e. the
@@ -1681,7 +1696,7 @@ private static Object js_lastIndexOf(Context cx, Scriptable scope, Scriptable th
1681
1696
Object compareTo = args .length > 0 ? args [0 ] : Undefined .instance ;
1682
1697
1683
1698
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1684
- long length = getLengthProperty (cx , o , false );
1699
+ long length = getLengthProperty (cx , o );
1685
1700
/*
1686
1701
* From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
1687
1702
* The index at which to start searching backwards. Defaults to the
@@ -1788,7 +1803,7 @@ private static Boolean js_includes(Context cx, Scriptable scope, Scriptable this
1788
1803
private static Object js_fill (Context cx , Scriptable scope , Scriptable thisObj , Object [] args )
1789
1804
{
1790
1805
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1791
- long len = getLengthProperty (cx , o , false );
1806
+ long len = getLengthProperty (cx , o );
1792
1807
1793
1808
long relativeStart = 0 ;
1794
1809
if (args .length >= 2 ) {
@@ -1825,7 +1840,7 @@ private static Object js_fill(Context cx, Scriptable scope, Scriptable thisObj,
1825
1840
private static Object js_copyWithin (Context cx , Scriptable scope , Scriptable thisObj , Object [] args )
1826
1841
{
1827
1842
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
1828
- long len = getLengthProperty (cx , o , false );
1843
+ long len = getLengthProperty (cx , o );
1829
1844
1830
1845
Object targetArg = (args .length >= 1 ) ? args [0 ] : Undefined .instance ;
1831
1846
long relativeTarget = (long ) ScriptRuntime .toInteger (targetArg );
@@ -1914,7 +1929,13 @@ private static Object iterativeMethod(Context cx, IdFunctionObject idFunctionObj
1914
1929
requireObjectCoercible (cx , o , idFunctionObject );
1915
1930
}
1916
1931
1917
- long length = getLengthProperty (cx , o , id == Id_map );
1932
+ long length = getLengthProperty (cx , o );
1933
+ // TODO: In the case of Id_filter, CreateDataPropertyOrThrow throws a TypeError instead of ArraySpeciesCreate.
1934
+ if ((id == Id_map || id == Id_filter ) && length > Integer .MAX_VALUE ) {
1935
+ String msg = ScriptRuntime .getMessageById ("msg.arraylength.bad" );
1936
+ throw ScriptRuntime .rangeError (msg );
1937
+ }
1938
+
1918
1939
Object callbackArg = args .length > 0 ? args [0 ] : Undefined .instance ;
1919
1940
if (callbackArg == null || !(callbackArg instanceof Function )) {
1920
1941
throw ScriptRuntime .notFunctionError (callbackArg );
@@ -2009,7 +2030,7 @@ private static Object reduceMethod(Context cx, int id, Scriptable scope,
2009
2030
{
2010
2031
Scriptable o = ScriptRuntime .toObject (cx , scope , thisObj );
2011
2032
2012
- long length = getLengthProperty (cx , o , false );
2033
+ long length = getLengthProperty (cx , o );
2013
2034
Object callbackArg = args .length > 0 ? args [0 ] : Undefined .instance ;
2014
2035
if (callbackArg == null || !(callbackArg instanceof Function )) {
2015
2036
throw ScriptRuntime .notFunctionError (callbackArg );
0 commit comments