microsoft/go-winio

Nil pointer dereference in prepareIo

Opened this issue · 0 comments

Sometimes, we get nil pointer derefence in this line in file.go:

func (f *win32File) prepareIo() (*ioOperation, error) {
	f.wg.Add(1)			// <---------- HERE
	if f.closing {
		return nil, ErrFileClosed
	}
	c := &ioOperation{}
	c.ch = make(chan ioResult)
	return c, nil
}

because f is nil. This is caused by a race condition in listenerRoutine(), when someone calls pipe.Close() before connectPipe() has a chance to start:

p, err := l.makeServerPipe()
if err == nil {
	// Wait for the client to connect.
	ch := make(chan error)
	go func() {
		ch <- connectPipe(p)		// <------ 2. we use niled pointer
	}()
	select {
	case err = <-ch:
		if err != nil {
			p.Close()
			p = nil
		}
	case <-l.closeCh:
		// Abort the connect request by closing the handle.
		p.Close()
		p = nil			// <----- 1. we nil the file pointer before connectPipe()
		err = <-ch
		if err == nil || err == ErrFileClosed {
			err = ErrPipeListenerClosed
		}
		closed = true
	}

This seems related to #31