aboutsummaryrefslogtreecommitdiffstats
path: root/prog/prog.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-03-12 11:06:01 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-03-13 10:31:21 +0000
commit3374743756461ab01a88a056ff039393a7b73a49 (patch)
treeb535640a2449530d4b84d9d4176e5825bc01b8c5 /prog/prog.go
parent43c7f3875016259bbb877ac58b831af47c92f06d (diff)
prog: tolerate differing array sizes in replaceArg
Structs may not change, but for arrays it's pretty normal. Let's remove this source of subtle panics by supporting arrays of differing sizes in replaceArg().
Diffstat (limited to 'prog/prog.go')
-rw-r--r--prog/prog.go20
1 files changed, 18 insertions, 2 deletions
diff --git a/prog/prog.go b/prog/prog.go
index da6f158bc..6b4853c7a 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -372,15 +372,31 @@ func replaceArg(arg, arg1 Arg) {
case *DataArg:
*a = *arg1.(*DataArg)
case *GroupArg:
+ _, isStruct := arg.Type().(*StructType)
a1 := arg1.(*GroupArg)
- if len(a.Inner) != len(a1.Inner) {
+ if isStruct && len(a.Inner) != len(a1.Inner) {
panic(fmt.Sprintf("replaceArg: group fields don't match: %v/%v",
len(a.Inner), len(a1.Inner)))
}
a.ArgCommon = a1.ArgCommon
- for i := range a.Inner {
+ // Replace min(|a|, |a1|) arguments.
+ for i := 0; i < len(a.Inner) && i < len(a1.Inner); i++ {
replaceArg(a.Inner[i], a1.Inner[i])
}
+ // Remove extra arguments of a.
+ for len(a.Inner) > len(a1.Inner) {
+ i := len(a.Inner) - 1
+ removeArg(a.Inner[i])
+ a.Inner[i] = nil
+ a.Inner = a.Inner[:i]
+ }
+ // Add extra arguments to a.
+ for i := len(a.Inner); i < len(a1.Inner); i++ {
+ a.Inner = append(a.Inner, a1.Inner[i])
+ }
+ if debug && len(a.Inner) != len(a1.Inner) {
+ panic("replaceArg implementation bug")
+ }
default:
panic(fmt.Sprintf("replaceArg: bad arg kind %#v", arg))
}