Skip to content

Commit c6db2fe

Browse files
authored
fix(codewhisperer): handle out of bounds endLine (#4254)
* fix(codewhisperer): handle out of bounds endLine * reduce code duplication
1 parent 71c6d99 commit c6db2fe

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "CodeWhisperer: handle exception when code scan service returns out of bounds line numbers"
4+
}

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ import java.time.Instant
5555
import java.util.Base64
5656
import java.util.UUID
5757
import kotlin.coroutines.coroutineContext
58+
import kotlin.math.max
59+
import kotlin.math.min
5860

5961
class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
6062
private val clientToken: UUID = UUID.randomUUID()
@@ -308,7 +310,8 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
308310
runReadAction {
309311
FileDocumentManager.getInstance().getDocument(file)
310312
}?.let { document ->
311-
val endCol = document.getLineEndOffset(it.endLine - 1) - document.getLineStartOffset(it.endLine - 1) + 1
313+
val endLineInDocument = min(max(0, it.endLine - 1), document.lineCount - 1)
314+
val endCol = document.getLineEndOffset(endLineInDocument) - document.getLineStartOffset(endLineInDocument) + 1
312315
CodeWhispererCodeScanIssue(
313316
startLine = it.startLine,
314317
startCol = 1,

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh
124124
assertThat(res).hasSize(2)
125125
}
126126

127+
@Test
128+
fun `test mapToCodeScanIssues - handles index out of bounds`() {
129+
val recommendations = listOf(
130+
fakeListCodeScanFindingsOutOfBoundsIndexResponse.codeScanFindings(),
131+
)
132+
val res = codeScanSessionSpy.mapToCodeScanIssues(recommendations)
133+
assertThat(res).hasSize(1)
134+
}
135+
127136
@Test
128137
fun `test run() - happypath`() {
129138
assertNotNull(sessionConfigSpy)

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTestBase.kt

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ open class CodeWhispererCodeScanTestBase(projectRule: CodeInsightTestFixtureRule
7676
internal lateinit var fakeCreateCodeScanResponseFailed: CreateCodeScanResponse
7777
internal lateinit var fakeCreateCodeScanResponsePending: CreateCodeScanResponse
7878
internal lateinit var fakeListCodeScanFindingsResponse: ListCodeScanFindingsResponse
79+
internal lateinit var fakeListCodeScanFindingsOutOfBoundsIndexResponse: ListCodeScanFindingsResponse
7980
internal lateinit var fakeGetCodeScanResponse: GetCodeScanResponse
8081
internal lateinit var fakeGetCodeScanResponsePending: GetCodeScanResponse
8182
internal lateinit var fakeGetCodeScanResponseFailed: GetCodeScanResponse
@@ -108,52 +109,41 @@ open class CodeWhispererCodeScanTestBase(projectRule: CodeInsightTestFixtureRule
108109
)
109110
}
110111

111-
private fun setupCodeScanFindings(filePath: Path) = """
112-
[
113-
{
114-
"filePath": "${filePath.systemIndependentPath}",
115-
"startLine": 1,
116-
"endLine": 2,
117-
"title": "test",
118-
"description": {
119-
"text": "global variable",
120-
"markdown": "### global variable"
121-
},
122-
"detectorId": "detectorId",
123-
"detectorName": "detectorName",
124-
"findingId": "findingId",
125-
"relatedVulnerabilities": [],
126-
"severity": "severity",
127-
"remediation": {
128-
"recommendation": {
129-
"text": "recommendationText",
130-
"url": "recommendationUrl"
131-
},
132-
"suggestedFixes": []
133-
}
112+
private fun setupCodeScanFinding(filePath: Path, startLine: Int, endLine: Int) = """
113+
{
114+
"filePath": "${filePath.systemIndependentPath}",
115+
"startLine": $startLine,
116+
"endLine": $endLine,
117+
"title": "test",
118+
"description": {
119+
"text": "global variable",
120+
"markdown": "### global variable"
134121
},
135-
{
136-
"filePath": "${filePath.systemIndependentPath}",
137-
"startLine": 1,
138-
"endLine": 2,
139-
"title": "test",
140-
"description": {
141-
"text": "global variable",
142-
"markdown": "### global variable"
122+
"detectorId": "detectorId",
123+
"detectorName": "detectorName",
124+
"findingId": "findingId",
125+
"relatedVulnerabilities": [],
126+
"severity": "severity",
127+
"remediation": {
128+
"recommendation": {
129+
"text": "recommendationText",
130+
"url": "recommendationUrl"
143131
},
144-
"detectorId": "detectorId",
145-
"detectorName": "detectorName",
146-
"findingId": "findingId",
147-
"relatedVulnerabilities": [],
148-
"severity": "severity",
149-
"remediation": {
150-
"recommendation": {
151-
"text": "recommendationText",
152-
"url": "recommendationUrl"
153-
},
154-
"suggestedFixes": []
155-
}
132+
"suggestedFixes": []
156133
}
134+
}
135+
""".trimIndent()
136+
137+
private fun setupCodeScanFindings(filePath: Path) = """
138+
[
139+
${setupCodeScanFinding(filePath, 1, 2)},
140+
${setupCodeScanFinding(filePath, 1, 2)}
141+
]
142+
"""
143+
144+
private fun setupCodeScanFindingsOutOfBounds(filePath: Path) = """
145+
[
146+
${setupCodeScanFinding(filePath, 99999, 99999)}
157147
]
158148
"""
159149

@@ -187,6 +177,11 @@ open class CodeWhispererCodeScanTestBase(projectRule: CodeInsightTestFixtureRule
187177
.responseMetadata(metadata)
188178
.build() as ListCodeScanFindingsResponse
189179

180+
fakeListCodeScanFindingsOutOfBoundsIndexResponse = ListCodeScanFindingsResponse.builder()
181+
.codeScanFindings(setupCodeScanFindingsOutOfBounds(filePath))
182+
.responseMetadata(metadata)
183+
.build() as ListCodeScanFindingsResponse
184+
190185
fakeGetCodeScanResponse = GetCodeScanResponse.builder()
191186
.status(CodeScanStatus.COMPLETED)
192187
.responseMetadata(metadata)

0 commit comments

Comments
 (0)