fix: bounds check, CanSet guard, and call.Failed on unpack error

- call.go: guard against struct fields > ABI output count (panic)
- call.go: check field.CanSet() before field.Set() (panic on unexported fields)
- caller.go: set call.Failed=true when CanFail=true and unpack fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
cary 2026-04-18 15:55:51 +08:00
parent c06f5fda53
commit ff027d0059
2 changed files with 7 additions and 0 deletions

View file

@ -108,8 +108,14 @@ func (call *Call) Unpack(b []byte) error {
}
fieldCount := t.NumField()
if fieldCount > len(out) {
return fmt.Errorf("struct has %d fields but ABI returned %d values", fieldCount, len(out))
}
for i := 0; i < fieldCount; i++ {
field := t.Field(i)
if !field.CanSet() {
return fmt.Errorf("field %d (%s) is not settable (unexported?)", i, t.Type().Field(i).Name)
}
converted := abi.ConvertType(out[i], field.Interface())
field.Set(reflect.ValueOf(converted))
}

View file

@ -85,6 +85,7 @@ func (caller *Caller) calls(opts *bind.CallOpts, calls ...*Call) ([]*Call, error
call.Failed = !result.Success
if err := call.Unpack(result.ReturnData); err != nil {
if call.CanFail {
call.Failed = true // mark as failed so callers don't need to inspect Outputs
log.Println(fmt.Errorf("failed to unpack call outputs at index [%d]: %v", i, err))
continue
}