Skip to content

Commit 89b7dba

Browse files
committed
fix: add bounds checks to prevent slice bounds out of range panic
1 parent 1ca5a2d commit 89b7dba

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

internal/ls/autoimports.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,27 @@ func (e *exportInfoMap) add(
117117
topLevelNodeModulesIndex := nodeModulesPathParts.TopLevelNodeModulesIndex
118118
topLevelPackageNameIndex := nodeModulesPathParts.TopLevelPackageNameIndex
119119
packageRootIndex := nodeModulesPathParts.PackageRootIndex
120-
packageName = module.UnmangleScopedPackageName(modulespecifiers.GetPackageNameFromTypesPackageName(moduleFile.FileName()[topLevelPackageNameIndex+1 : packageRootIndex]))
121-
if strings.HasPrefix(string(importingFile), string(moduleFile.Path())[0:topLevelNodeModulesIndex]) {
122-
nodeModulesPath := moduleFile.FileName()[0 : topLevelPackageNameIndex+1]
123-
if prevDeepestNodeModulesPath, ok := e.packages[packageName]; ok {
124-
prevDeepestNodeModulesIndex := strings.Index(prevDeepestNodeModulesPath, "/node_modules/")
125-
if topLevelNodeModulesIndex > prevDeepestNodeModulesIndex {
120+
121+
// Bounds check to prevent slice bounds out of range panic
122+
fileName := moduleFile.FileName()
123+
if topLevelPackageNameIndex+1 >= 0 && packageRootIndex >= 0 && topLevelPackageNameIndex+1 <= packageRootIndex && packageRootIndex <= len(fileName) {
124+
packageName = module.UnmangleScopedPackageName(modulespecifiers.GetPackageNameFromTypesPackageName(fileName[topLevelPackageNameIndex+1 : packageRootIndex]))
125+
}
126+
127+
// Bounds check for module path slice
128+
modulePath := string(moduleFile.Path())
129+
if topLevelNodeModulesIndex >= 0 && topLevelNodeModulesIndex <= len(modulePath) && strings.HasPrefix(string(importingFile), modulePath[0:topLevelNodeModulesIndex]) {
130+
// Bounds check for node modules path slice
131+
if topLevelPackageNameIndex+1 >= 0 && topLevelPackageNameIndex+1 <= len(fileName) {
132+
nodeModulesPath := fileName[0 : topLevelPackageNameIndex+1]
133+
if prevDeepestNodeModulesPath, ok := e.packages[packageName]; ok {
134+
prevDeepestNodeModulesIndex := strings.Index(prevDeepestNodeModulesPath, "/node_modules/")
135+
if topLevelNodeModulesIndex > prevDeepestNodeModulesIndex {
136+
e.packages[packageName] = nodeModulesPath
137+
}
138+
} else {
126139
e.packages[packageName] = nodeModulesPath
127140
}
128-
} else {
129-
e.packages[packageName] = nodeModulesPath
130141
}
131142
}
132143
}

internal/ls/autoimportsexportinfo.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ func (l *LanguageService) searchExportInfosForCompletions(
100100
return false
101101
}
102102
// Do not try to auto-import something with a lowercase first letter for a JSX tag
103+
if len(symbolName) == 0 {
104+
symbolNameMatches[symbolName] = false
105+
return false
106+
}
103107
firstChar := rune(symbolName[0])
104108
if isRightOfOpenTag && (firstChar < 'A' || firstChar > 'Z') {
105109
symbolNameMatches[symbolName] = false

internal/ls/completions.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,7 +2376,14 @@ var wordSeparators = collections.NewSetFromItems(
23762376
// e.g. for "abc def.ghi|jkl", the word length is 3 and the word start is 'g'.
23772377
func getWordLengthAndStart(sourceFile *ast.SourceFile, position int) (wordLength int, wordStart rune) {
23782378
// !!! Port other case of vscode's `DEFAULT_WORD_REGEXP` that covers words that start like numbers, e.g. -123.456abcd.
2379-
text := sourceFile.Text()[:position]
2379+
2380+
// Bounds check to prevent slice bounds out of range panic
2381+
sourceText := sourceFile.Text()
2382+
if position < 0 || position > len(sourceText) {
2383+
return 0, 0
2384+
}
2385+
2386+
text := sourceText[:position]
23802387
totalSize := 0
23812388
var firstRune rune
23822389
for r, size := utf8.DecodeLastRuneInString(text); size != 0; r, size = utf8.DecodeLastRuneInString(text[:len(text)-totalSize]) {
@@ -2485,7 +2492,13 @@ func getFilterText(
24852492

24862493
// Ported from vscode's `provideCompletionItems`.
24872494
func getDotAccessor(file *ast.SourceFile, position int) string {
2488-
text := file.Text()[:position]
2495+
// Bounds check to prevent slice bounds out of range panic
2496+
fileText := file.Text()
2497+
if position < 0 || position > len(fileText) {
2498+
return ""
2499+
}
2500+
2501+
text := fileText[:position]
24892502
totalSize := 0
24902503
if strings.HasSuffix(text, "?.") {
24912504
totalSize += 2

0 commit comments

Comments
 (0)