fix: address code scanning alerts (#240)

This commit is contained in:
Vasanth T
2026-04-03 14:52:35 +05:30
committed by GitHub
parent f3a984dde1
commit 7c0ea68b65
15 changed files with 205 additions and 73 deletions

View File

@@ -0,0 +1,40 @@
import { expect, test } from 'bun:test'
import { applySedSubstitution, type SedEditInfo } from './sedEditParser.js'
function sedInfo(pattern: string, replacement: string, extendedRegex = false): SedEditInfo {
return {
filePath: 'example.txt',
pattern,
replacement,
flags: 'g',
extendedRegex,
}
}
test('BRE mode keeps unescaped plus literal', () => {
const result = applySedSubstitution(
'a+b and aaab',
sedInfo('a+b', 'literal-plus'),
)
expect(result).toBe('literal-plus and aaab')
})
test('BRE mode treats escaped plus as one-or-more', () => {
const result = applySedSubstitution(
'abbb and a+b',
sedInfo('ab\\+', 'one-or-more'),
)
expect(result).toBe('one-or-more and a+b')
})
test('BRE mode preserves escaped backslashes', () => {
const result = applySedSubstitution(
String.raw`foo\bar foo/bar`,
sedInfo(String.raw`foo\\bar`, 'backslash-match'),
)
expect(result).toBe('backslash-match foo/bar')
})

View File

@@ -7,18 +7,6 @@ import { randomBytes } from 'crypto'
import { tryParseShellCommand } from '../../utils/bash/shellQuote.js'
// BRE→ERE conversion placeholders (null-byte sentinels, never appear in user input)
const BACKSLASH_PLACEHOLDER = '\x00BACKSLASH\x00'
const PLUS_PLACEHOLDER = '\x00PLUS\x00'
const QUESTION_PLACEHOLDER = '\x00QUESTION\x00'
const PIPE_PLACEHOLDER = '\x00PIPE\x00'
const LPAREN_PLACEHOLDER = '\x00LPAREN\x00'
const RPAREN_PLACEHOLDER = '\x00RPAREN\x00'
const BACKSLASH_PLACEHOLDER_RE = new RegExp(BACKSLASH_PLACEHOLDER, 'g')
const PLUS_PLACEHOLDER_RE = new RegExp(PLUS_PLACEHOLDER, 'g')
const QUESTION_PLACEHOLDER_RE = new RegExp(QUESTION_PLACEHOLDER, 'g')
const PIPE_PLACEHOLDER_RE = new RegExp(PIPE_PLACEHOLDER, 'g')
const LPAREN_PLACEHOLDER_RE = new RegExp(LPAREN_PLACEHOLDER, 'g')
const RPAREN_PLACEHOLDER_RE = new RegExp(RPAREN_PLACEHOLDER, 'g')
export type SedEditInfo = {
/** The file path being edited */
@@ -33,6 +21,40 @@ export type SedEditInfo = {
extendedRegex: boolean
}
function convertBrePatternToJs(pattern: string): string {
let result = ''
for (let i = 0; i < pattern.length; i++) {
const char = pattern[i]!
if (char === '\\') {
const next = pattern[i + 1]
if (next === undefined) {
result += '\\\\'
continue
}
if (next === '\\') {
result += '\\\\'
} else if ('+?|()'.includes(next)) {
result += next
} else {
result += `\\${next}`
}
i++
continue
}
if ('+?|()'.includes(char)) {
result += `\\${char}`
continue
}
result += char
}
return result
}
/**
* Check if a command is a sed in-place edit command
* Returns true only for simple sed -i 's/pattern/replacement/flags' file commands
@@ -273,28 +295,7 @@ export function applySedSubstitution(
// ERE/JS: + means "one or more", \+ is literal
// We need to convert BRE escaping to ERE for JavaScript regex
if (!sedInfo.extendedRegex) {
jsPattern = jsPattern
// Step 1: Protect literal backslashes (\\) first - in both BRE and ERE, \\ is literal backslash
.replace(/\\\\/g, BACKSLASH_PLACEHOLDER)
// Step 2: Replace escaped metacharacters with placeholders (these should become unescaped in JS)
.replace(/\\\+/g, PLUS_PLACEHOLDER)
.replace(/\\\?/g, QUESTION_PLACEHOLDER)
.replace(/\\\|/g, PIPE_PLACEHOLDER)
.replace(/\\\(/g, LPAREN_PLACEHOLDER)
.replace(/\\\)/g, RPAREN_PLACEHOLDER)
// Step 3: Escape unescaped metacharacters (these are literal in BRE)
.replace(/\+/g, '\\+')
.replace(/\?/g, '\\?')
.replace(/\|/g, '\\|')
.replace(/\(/g, '\\(')
.replace(/\)/g, '\\)')
// Step 4: Replace placeholders with their JS equivalents
.replace(BACKSLASH_PLACEHOLDER_RE, '\\\\')
.replace(PLUS_PLACEHOLDER_RE, '+')
.replace(QUESTION_PLACEHOLDER_RE, '?')
.replace(PIPE_PLACEHOLDER_RE, '|')
.replace(LPAREN_PLACEHOLDER_RE, '(')
.replace(RPAREN_PLACEHOLDER_RE, ')')
jsPattern = convertBrePatternToJs(jsPattern)
}
// Unescape sed-specific escapes in replacement