mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
Fix subtle range bug in String.substring (uint => int64)
Was looking for negative in the following calculation: uint(0) - uint(3) => uint(0)
This commit is contained in:
parent
ec902a6452
commit
bf322e56ee
2
Makefile
2
Makefile
|
@ -45,6 +45,8 @@ TEST := -v --run _underscore_
|
|||
TEST := -v --run _parseFloat
|
||||
TEST := -v --run _underscore_utility
|
||||
TEST := -v --run Array_splice
|
||||
TEST := -v --run String_substring
|
||||
TEST := -v --run String_slice
|
||||
TEST := .
|
||||
|
||||
test: test-i
|
||||
|
|
|
@ -162,11 +162,11 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
length := uint(toUint32(thisObject.get("length")))
|
||||
|
||||
start := valueToRangeIndex(call.Argument(0), length, false)
|
||||
deleteCount := valueToRangeIndex(call.Argument(1), length-start, true)
|
||||
deleteCount := valueToRangeIndex(call.Argument(1), uint(int64(length)-start), true)
|
||||
valueArray := make([]Value, deleteCount)
|
||||
|
||||
for index := uint(0); index < deleteCount; index++ {
|
||||
indexString := arrayIndexToString(start + index)
|
||||
for index := int64(0); index < deleteCount; index++ {
|
||||
indexString := arrayIndexToString(uint(start + index))
|
||||
if thisObject.hasProperty(indexString) {
|
||||
valueArray[index] = thisObject.get(indexString)
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
// length 8 - delete 4 @ start 1
|
||||
|
||||
itemList := []Value{}
|
||||
itemCount := uint(len(call.ArgumentList))
|
||||
itemCount := int64(len(call.ArgumentList))
|
||||
if itemCount > 2 {
|
||||
itemCount -= 2 // Less the first two arguments
|
||||
itemList = call.ArgumentList[2:]
|
||||
|
@ -186,14 +186,15 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
}
|
||||
if itemCount < deleteCount {
|
||||
// The Object/Array is shrinking
|
||||
stop := length - deleteCount // The new length of the Object/Array before
|
||||
stop := int64(length) - deleteCount
|
||||
// The new length of the Object/Array before
|
||||
// appending the itemList remainder
|
||||
// Stopping at the lower bound of the insertion:
|
||||
// Move an item from the after the deleted portion
|
||||
// to a position after the inserted portion
|
||||
for index := start; index < stop; index++ {
|
||||
from := arrayIndexToString(index + deleteCount) // Position just after deletion
|
||||
to := arrayIndexToString(index + itemCount) // Position just after splice (insertion)
|
||||
from := arrayIndexToString(uint(index + deleteCount)) // Position just after deletion
|
||||
to := arrayIndexToString(uint(index + itemCount)) // Position just after splice (insertion)
|
||||
if thisObject.hasProperty(from) {
|
||||
thisObject.put(to, thisObject.get(from), true)
|
||||
} else {
|
||||
|
@ -203,8 +204,8 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
// Delete off the end
|
||||
// We don't bother to delete below <stop + itemCount> (if any) since those
|
||||
// will be overwritten anyway
|
||||
for index := length; index > (stop + itemCount); index-- {
|
||||
thisObject.delete(arrayIndexToString(index-1), true)
|
||||
for index := int64(length); index > (stop + itemCount); index-- {
|
||||
thisObject.delete(arrayIndexToString(uint(index-1)), true)
|
||||
}
|
||||
} else if itemCount > deleteCount {
|
||||
// The Object/Array is growing
|
||||
|
@ -214,9 +215,9 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
// Starting from the upper bound of the deletion:
|
||||
// Move an item from the after the deleted portion
|
||||
// to a position after the inserted portion
|
||||
for index := length - deleteCount; index > start; index-- {
|
||||
from := arrayIndexToString(index + deleteCount - 1)
|
||||
to := arrayIndexToString(index + itemCount - 1)
|
||||
for index := int64(length) - deleteCount; index > start; index-- {
|
||||
from := arrayIndexToString(uint(index + deleteCount - 1))
|
||||
to := arrayIndexToString(uint(index + itemCount - 1))
|
||||
if thisObject.hasProperty(from) {
|
||||
thisObject.put(to, thisObject.get(from), true)
|
||||
} else {
|
||||
|
@ -225,10 +226,10 @@ func builtinArray_splice(call FunctionCall) Value {
|
|||
}
|
||||
}
|
||||
|
||||
for index := uint(0); index < itemCount; index++ {
|
||||
thisObject.put(arrayIndexToString(index+start), itemList[index], true)
|
||||
for index := int64(0); index < itemCount; index++ {
|
||||
thisObject.put(arrayIndexToString(uint(index+start)), itemList[index], true)
|
||||
}
|
||||
thisObject.put("length", toValue(length+itemCount-deleteCount), true)
|
||||
thisObject.put("length", toValue(uint(int64(length)+itemCount-deleteCount)), true)
|
||||
|
||||
return toValue(call.runtime.newArray(valueArray))
|
||||
}
|
||||
|
@ -250,8 +251,8 @@ func builtinArray_slice(call FunctionCall) Value {
|
|||
if _arrayStash, ok := thisObject.stash.(*_arrayStash); ok {
|
||||
copy(sliceValueArray, _arrayStash.valueArray[start:start+sliceLength])
|
||||
} else {
|
||||
for index := uint(0); index < sliceLength; index++ {
|
||||
from := arrayIndexToString(index + start)
|
||||
for index := int64(0); index < sliceLength; index++ {
|
||||
from := arrayIndexToString(uint(index + start))
|
||||
if thisObject.hasProperty(from) {
|
||||
sliceValueArray[index] = thisObject.get(from)
|
||||
}
|
||||
|
|
|
@ -388,7 +388,7 @@ func builtinString_slice(call FunctionCall) Value {
|
|||
|
||||
length := uint(len(target))
|
||||
start, end := rangeStartEnd(call.ArgumentList, length, false)
|
||||
if start >= length || end-start <= 0 {
|
||||
if end-start <= 0 {
|
||||
return toValue("")
|
||||
}
|
||||
return toValue(target[start:end])
|
||||
|
|
37
otto_.go
37
otto_.go
|
@ -62,35 +62,38 @@ func valueOfArrayIndex(list []Value, index int) Value {
|
|||
|
||||
// A range index can be anything from 0 up to length. It is NOT safe to use as an index
|
||||
// to an array, but is useful for slicing and in some ECMA algorithms.
|
||||
func valueToRangeIndex(indexValue Value, length uint, negativeIsZero bool) uint {
|
||||
index := toIntegerFloat(indexValue)
|
||||
if negativeIsZero {
|
||||
index := uint(math.Max(index, 0))
|
||||
// minimum(index, length)
|
||||
if index >= length {
|
||||
return length
|
||||
func valueToRangeIndex(indexValue Value, length uint, negativeIsZero bool) int64 {
|
||||
{
|
||||
index := toIntegerFloat(indexValue)
|
||||
length := float64(length)
|
||||
if negativeIsZero {
|
||||
index := math.Max(index, 0)
|
||||
// minimum(index, length)
|
||||
if index >= length {
|
||||
index = length
|
||||
}
|
||||
return int64(uint(index))
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
if index < 0 {
|
||||
index = math.Max(index+float64(length), 0)
|
||||
} else {
|
||||
index = math.Min(index, float64(length))
|
||||
if index < 0 {
|
||||
index = math.Max(index+length, 0)
|
||||
} else {
|
||||
index = math.Min(index, length)
|
||||
}
|
||||
return int64(uint(index))
|
||||
}
|
||||
return uint(index)
|
||||
}
|
||||
|
||||
func rangeStartEnd(array []Value, size uint, negativeIsZero bool) (start, end uint) {
|
||||
func rangeStartEnd(array []Value, size uint, negativeIsZero bool) (start, end int64) {
|
||||
start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero)
|
||||
if len(array) == 1 {
|
||||
// If there is only the start argument, then end = size
|
||||
end = size
|
||||
end = int64(size)
|
||||
return
|
||||
}
|
||||
|
||||
// Assuming the argument is undefined...
|
||||
end = size
|
||||
end = int64(size)
|
||||
endValue := valueOfArrayIndex(array, 1)
|
||||
if !endValue.IsUndefined() {
|
||||
// Which it is not, so get the value as an array index
|
||||
|
|
Loading…
Reference in New Issue
Block a user