proc: if a reslice operator is used load the whole slice (#3623)
When the users uses a reslice operation load the whole resliced variable, ignoring the MaxArrayValues setting. Only apply this when the 'high' part is specified and a literal and the 'low' part is either unspecified or a literal. Fixes #3600
This commit is contained in:
parent
ef20fbbf12
commit
6cd0b70b30
@ -1904,7 +1904,7 @@ func (scope *EvalScope) evalReslice(op *evalop.Reslice, stack *evalStack) {
|
||||
stack.err = fmt.Errorf("can not slice %q", exprToString(op.Node.X))
|
||||
return
|
||||
}
|
||||
stack.pushErr(xev.reslice(low, high))
|
||||
stack.pushErr(xev.reslice(low, high, op.TrustLen))
|
||||
return
|
||||
case reflect.Map:
|
||||
if op.Node.High != nil {
|
||||
@ -1921,7 +1921,7 @@ func (scope *EvalScope) evalReslice(op *evalop.Reslice, stack *evalStack) {
|
||||
return
|
||||
case reflect.Ptr:
|
||||
if xev.Flags&VariableCPtr != 0 {
|
||||
stack.pushErr(xev.reslice(low, high))
|
||||
stack.pushErr(xev.reslice(low, high, op.TrustLen))
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
@ -2550,7 +2550,7 @@ func (v *Variable) LoadResliced(start int, cfg LoadConfig) (newV *Variable, err
|
||||
if high > v.Len {
|
||||
high = v.Len
|
||||
}
|
||||
newV, err = v.reslice(low, high)
|
||||
newV, err = v.reslice(low, high, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -2566,7 +2566,7 @@ func (v *Variable) LoadResliced(start int, cfg LoadConfig) (newV *Variable, err
|
||||
return newV, nil
|
||||
}
|
||||
|
||||
func (v *Variable) reslice(low int64, high int64) (*Variable, error) {
|
||||
func (v *Variable) reslice(low int64, high int64, trustLen bool) (*Variable, error) {
|
||||
wrong := false
|
||||
cptrNeedsFakeSlice := false
|
||||
if v.Flags&VariableCPtr == 0 {
|
||||
@ -2606,6 +2606,9 @@ func (v *Variable) reslice(low int64, high int64) (*Variable, error) {
|
||||
r.stride = v.stride
|
||||
r.fieldType = v.fieldType
|
||||
r.Flags = v.Flags
|
||||
if trustLen {
|
||||
r.Flags |= variableTrustLen
|
||||
}
|
||||
r.reg = v.reg
|
||||
|
||||
return r, nil
|
||||
|
||||
@ -483,6 +483,7 @@ func (ctx *compileCtx) compileReslice(node *ast.SliceExpr) error {
|
||||
return err
|
||||
}
|
||||
|
||||
trustLen := true
|
||||
hasHigh := false
|
||||
if node.High != nil {
|
||||
hasHigh = true
|
||||
@ -490,6 +491,10 @@ func (ctx *compileCtx) compileReslice(node *ast.SliceExpr) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, isbasiclit := node.High.(*ast.BasicLit)
|
||||
trustLen = trustLen && isbasiclit
|
||||
} else {
|
||||
trustLen = false
|
||||
}
|
||||
|
||||
if node.Low != nil {
|
||||
@ -497,11 +502,13 @@ func (ctx *compileCtx) compileReslice(node *ast.SliceExpr) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, isbasiclit := node.Low.(*ast.BasicLit)
|
||||
trustLen = trustLen && isbasiclit
|
||||
} else {
|
||||
ctx.pushOp(&PushConst{constant.MakeInt64(0)})
|
||||
}
|
||||
|
||||
ctx.pushOp(&Reslice{Node: node, HasHigh: hasHigh})
|
||||
ctx.pushOp(&Reslice{Node: node, HasHigh: hasHigh, TrustLen: trustLen})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -114,9 +114,11 @@ func (*TypeCast) depthCheck() (npop, npush int) { return 1, 1 }
|
||||
// If HasHigh is set it pops three variables, low, high and v, and pushes
|
||||
// v[low:high].
|
||||
// Otherwise it pops two variables, low and v, and pushes v[low:].
|
||||
// If TrustLen is set when the variable resulting from the reslice is loaded it will be fully loaded.
|
||||
type Reslice struct {
|
||||
HasHigh bool
|
||||
Node *ast.SliceExpr
|
||||
HasHigh bool
|
||||
TrustLen bool
|
||||
Node *ast.SliceExpr
|
||||
}
|
||||
|
||||
func (op *Reslice) depthCheck() (npop, npush int) {
|
||||
|
||||
@ -86,6 +86,9 @@ const (
|
||||
VariableCPtr
|
||||
// VariableCPURegister means this variable is a CPU register.
|
||||
VariableCPURegister
|
||||
// variableTrustLen means that when this variable is loaded its length
|
||||
// should be trusted and used instead of MaxArrayValues
|
||||
variableTrustLen
|
||||
)
|
||||
|
||||
// Variable represents a variable. It contains the address, name,
|
||||
@ -1683,7 +1686,7 @@ func (v *Variable) loadArrayValues(recurseLevel int, cfg LoadConfig) {
|
||||
|
||||
count := v.Len
|
||||
// Cap number of elements
|
||||
if count > int64(cfg.MaxArrayValues) {
|
||||
if (v.Flags&variableTrustLen == 0) && (count > int64(cfg.MaxArrayValues)) {
|
||||
count = int64(cfg.MaxArrayValues)
|
||||
}
|
||||
if v.Base+uint64(v.stride*count) < v.Base {
|
||||
|
||||
@ -553,8 +553,8 @@ func getEvalExpressionTestCases() []varTest {
|
||||
{"str1[11]", false, "", "", "byte", fmt.Errorf("index out of bounds")},
|
||||
|
||||
// slice/array/string reslicing
|
||||
{"a1[2:4]", false, "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string len: 2, cap: 2, [...]", "[]string", nil},
|
||||
{"s1[2:4]", false, "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string len: 2, cap: 2, [...]", "[]string", nil},
|
||||
{"a1[2:4]", false, "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string", nil},
|
||||
{"s1[2:4]", false, "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string len: 2, cap: 2, [\"three\",\"four\"]", "[]string", nil},
|
||||
{"str1[2:4]", false, "\"23\"", "\"23\"", "string", nil},
|
||||
{"str1[0:11]", false, "\"01234567890\"", "\"01234567890\"", "string", nil},
|
||||
{"str1[:3]", false, "\"012\"", "\"012\"", "string", nil},
|
||||
@ -562,6 +562,7 @@ func getEvalExpressionTestCases() []varTest {
|
||||
{"str1[0:12]", false, "", "", "string", fmt.Errorf("index out of bounds")},
|
||||
{"str1[5:3]", false, "", "", "string", fmt.Errorf("index out of bounds")},
|
||||
{"str1[11:]", false, "\"\"", "\"\"", "string", nil},
|
||||
{"longbyteslice[:70]", false, "[]uint8 len: 70, cap: 70, [118,101,114,121,32,108,111,110,103,32,115,116,114,105,110,103,32,48,49,50,51,52,53,54,55,56,57,97,48,49,50,51,52,53,54,55,56,57,98,48,49,50,51,52,53,54,55,56,57,99,48,49,50,51,52,53,54,55,56,57,100,48,49,50,51,52,53,54,55,56]", "[]uint8 len: 70, cap: 70, [118,101,114,121,32,108,111,110,103,32,115,116,114,105,110,103,32,48,49,50,51,52,53,54,55,56,57,97,48,49,50,51,52,53,54,55,56,57,98,48,49,50,51,52,53,54,55,56,57,99,48,49,50,51,52,53,54,55,56,57,100,48,49,50,51,52,53,54,55,56]", "[]uint8", nil},
|
||||
|
||||
// NaN and Inf floats
|
||||
{"pinf", false, "+Inf", "+Inf", "float64", nil},
|
||||
@ -1579,7 +1580,7 @@ func TestCgoEval(t *testing.T) {
|
||||
{"v", true, "*0", "(*int)(…", "*int", nil},
|
||||
{"v[1]", false, "1", "1", "int", nil},
|
||||
{"v[90]", false, "90", "90", "int", nil},
|
||||
{"v[:5]", false, "[]int len: 5, cap: 5, [0,1,2,3,4]", "[]int len: 5, cap: 5, [...]", "[]int", nil},
|
||||
{"v[:5]", false, "[]int len: 5, cap: 5, [0,1,2,3,4]", "[]int len: 5, cap: 5, [0,1,2,3,4]", "[]int", nil},
|
||||
{"v_align_check", true, "*align_check {a: 0, b: 0}", "(*struct align_check)(…", "*struct align_check", nil},
|
||||
{"v_align_check[1]", false, "align_check {a: 1, b: 1}", "align_check {a: 1, b: 1}", "align_check", nil},
|
||||
{"v_align_check[90]", false, "align_check {a: 90, b: 90}", "align_check {a: 90, b: 90}", "align_check", nil},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user