Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'bad access: nil dereference' when calling Error()/getMsg() method of type Error in terror/terror.go #576

Open
henng opened this issue Oct 12, 2019 · 2 comments

Comments

@henng
Copy link

henng commented Oct 12, 2019

Bug Report

  1. What did you do?
    Debugging a test case in TiDB and stuck in debug mode, see error of 'bad access: nil dereference'

Here's an exactly case:

  • There are some loggings like ddl/ddl.go:588, which calls job.String()
// logutil.BgLogger().Info("[ddl] start DDL job", zap.String("job", job.String()), zap.String("query", job.Query))


func (job *Job) String() string {
	rowCount := job.GetRowCount()
	return fmt.Sprintf("ID:%d, Type:%s, State:%s, SchemaState:%s, SchemaID:%d, TableID:%d, RowCount:%d, ArgLen:%d, start time: %v, Err:%v, ErrCount:%d, SnapshotVersion:%v",
		job.ID, job.Type, job.State, job.SchemaState, job.SchemaID, job.TableID, rowCount, len(job.Args), TSConvert2Time(job.StartTS), job.Error, job.ErrorCount, job.SnapshotVer)
}
  • We can see above, when calling fmt.Sprintf() with job.Error is a nil dereference, it will reach /your_go_root/src/fmt/print.go::printArg(), in this case arg == nil is not true.
func (p *pp) printArg(arg interface{}, verb rune) {
	p.arg = arg
	p.value = reflect.Value{}

	if arg == nil {
		switch verb {
		case 'T', 'v':
			p.fmt.padString(nilAngleString)
		default:
			p.badVerb(verb)
		}
		return
	}
       ......
}
  • Finally, we got /your_go_rootc/src/fmt/print.go::handleMethods(), in this case v or p.arg is a nil dereference cause it's from job.Error, and it is an error type casue job.Error is a pointer of terror.Error, so error occurs when calling v.Error().
switch verb {
	case 'v', 's', 'x', 'X', 'q':
		switch v := p.arg.(type) {
			case error:
				handled = true
				defer p.catchPanic(p.arg, verb, "Error")
				p.fmtString(v.Error(), verb)
				return
                                ......
                }
                ......
}

Here's a simple test case that you can re-produce the error in debug mode:

type ABC struct {
	a int64
	b bool
	c *terror.Error
}

func TestSprintf(t *testing.T) {
	abc := &ABC{c: nil}
	s := fmt.Sprintf("Testing's Err: %v", abc.c)
	println(s)
}
  1. What did you expect to see?

No Errors

  1. What did you see instead?

bad access: nil dereference

  1. What version of TiDB SQL Parser are you using?

[email protected]

@henng
Copy link
Author

henng commented Oct 12, 2019

Made a try to fix this, see #577

@bb7133
Copy link
Member

bb7133 commented Oct 29, 2020

Just a ping, @henng may you update #577 please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants