Skip to content

Commit 59f12cf

Browse files
authored
Fix nil pointer dereference in snapshotFS.GetFile for non-existent files (#1830)
1 parent 912f193 commit 59f12cf

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

internal/project/snapshot_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,23 @@ func TestSnapshot(t *testing.T) {
101101
assert.Check(t, snapshotAfter.fs.diskFiles["/home/projects/ts/p1/a.ts"] == nil)
102102
assert.Check(t, snapshotAfter.fs.diskFiles["/home/projects/ts/p2/b.ts"] != nil)
103103
})
104+
105+
t.Run("GetFile returns nil for non-existent files", func(t *testing.T) {
106+
t.Parallel()
107+
files := map[string]any{
108+
"/home/projects/TS/p1/tsconfig.json": "{}",
109+
"/home/projects/TS/p1/index.ts": "console.log('Hello, world!');",
110+
}
111+
session := setup(files)
112+
session.DidOpenFile(context.Background(), "file:///home/projects/TS/p1/index.ts", 1, files["/home/projects/TS/p1/index.ts"].(string), lsproto.LanguageKindTypeScript)
113+
snapshot, release := session.Snapshot()
114+
defer release()
115+
116+
handle := snapshot.GetFile("/home/projects/TS/p1/nonexistent.ts")
117+
assert.Check(t, handle == nil, "GetFile should return nil for non-existent file")
118+
119+
// Test that ReadFile returns false for non-existent file
120+
_, ok := snapshot.ReadFile("/home/projects/TS/p1/nonexistent.ts")
121+
assert.Check(t, !ok, "ReadFile should return false for non-existent file")
122+
})
104123
}

internal/project/snapshotfs.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type snapshotFS struct {
3030
readFiles collections.SyncMap[tspath.Path, memoizedDiskFile]
3131
}
3232

33-
type memoizedDiskFile func() *diskFile
33+
type memoizedDiskFile func() FileHandle
3434

3535
func (s *snapshotFS) FS() vfs.FS {
3636
return s.fs
@@ -43,16 +43,14 @@ func (s *snapshotFS) GetFile(fileName string) FileHandle {
4343
if file, ok := s.diskFiles[s.toPath(fileName)]; ok {
4444
return file
4545
}
46-
newEntry := memoizedDiskFile(sync.OnceValue(func() *diskFile {
46+
newEntry := memoizedDiskFile(sync.OnceValue(func() FileHandle {
4747
if contents, ok := s.fs.ReadFile(fileName); ok {
4848
return newDiskFile(fileName, contents)
4949
}
5050
return nil
5151
}))
52-
if entry, ok := s.readFiles.LoadOrStore(s.toPath(fileName), newEntry); ok {
53-
return entry()
54-
}
55-
return nil
52+
entry, _ := s.readFiles.LoadOrStore(s.toPath(fileName), newEntry)
53+
return entry()
5654
}
5755

5856
type snapshotFSBuilder struct {

0 commit comments

Comments
 (0)