os: make Readdir work as documented

Readdir's result should never contain a nil.

Fixes #5960.

R=golang-dev, rsc, bradfitz
CC=golang-dev
https://golang.org/cl/12261043
diff --git a/src/pkg/os/os_unix_test.go b/src/pkg/os/os_unix_test.go
index f8e330b..90bbdab 100644
--- a/src/pkg/os/os_unix_test.go
+++ b/src/pkg/os/os_unix_test.go
@@ -28,7 +28,7 @@
 }
 
 func TestChown(t *testing.T) {
-	// Chown is not supported under windows or Plan 9.
+	// Chown is not supported under windows os Plan 9.
 	// Plan9 provides a native ChownPlan9 version instead.
 	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
 		return
@@ -74,3 +74,41 @@
 		checkUidGid(t, f.Name(), int(sys.Uid), gid)
 	}
 }
+
+func TestReaddirWithBadLstat(t *testing.T) {
+	handle, err := Open(sfdir)
+	failfile := sfdir + "/" + sfname
+	if err != nil {
+		t.Fatalf("Couldn't open %s: %s", sfdir, err)
+	}
+
+	*LstatP = func(file string) (FileInfo, error) {
+		if file == failfile {
+			var fi FileInfo
+			return fi, ErrInvalid
+		}
+		return Lstat(file)
+	}
+	defer func() { *LstatP = Lstat }()
+
+	dirs, err := handle.Readdir(-1)
+	if err != ErrInvalid {
+		t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err)
+	}
+	foundfail := false
+	for _, dir := range dirs {
+		if dir.Name() == sfname {
+			foundfail = true
+			if dir.Sys() != nil {
+				t.Errorf("Expected Readdir for %s should not contain Sys", failfile)
+			}
+		} else {
+			if dir.Sys() == nil {
+				t.Errorf("Readdir for every file other than %s should contain Sys, but %s/%s didn't either", failfile, sfdir, dir.Name())
+			}
+		}
+	}
+	if !foundfail {
+		t.Fatalf("Expected %s from Readdir, but didn't find it", failfile)
+	}
+}