Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions packages/launch-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
const guessEditor = require('./guess')
const getArgumentsForFile = require('./get-args')
const constructWindowsLaunchCommand = require('./construct-windows-launch-command')
const parseFile = require('./parse-file')

function wrapErrorCallback(cb) {
return (fileName, errorMessage) => {
Expand All @@ -42,24 +43,6 @@
return false
}

const positionRE = /:(\d+)(:(\d+))?$/
function parseFile(file) {
// support `file://` protocol
if (file.startsWith('file://')) {
file = require('url').fileURLToPath(file)
}

const fileName = file.replace(positionRE, '')
const match = file.match(positionRE)
const lineNumber = match && match[1]
const columnNumber = match && match[3]
return {
fileName,
lineNumber,
columnNumber,
}
}

let currentChildProcess = null

function launchEditor(file, specifiedEditor, onErrorCallback) {
Expand All @@ -72,7 +55,7 @@

onErrorCallback = wrapErrorCallback(onErrorCallback)

if (process.platform === 'win32' && path.resolve(fileName).startsWith('\\\\')) {
if (process.platform === 'win32' && fileName.startsWith('\\\\')) {
return onErrorCallback(
fileName,
'UNC paths are not supported on Windows to avoid security issues. ' +
Expand Down Expand Up @@ -102,7 +85,7 @@

if (process.platform === 'win32') {
const launchCommand = constructWindowsLaunchCommand(editor, args)
currentChildProcess = childProcess.exec(launchCommand, {

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.
This shell command depends on an uncontrolled absolute path.
stdio: 'inherit',
shell: true,
})
Expand Down
23 changes: 23 additions & 0 deletions packages/launch-editor/parse-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const path = require('path')

const positionRE = /:(\d+)(:(\d+))?$/

module.exports = function parseFile(file) {
// support `file://` protocol
if (file.startsWith('file://')) {
file = require('url').fileURLToPath(file)
}

const unresolvedFileName = file.replace(positionRE, '')
const fileName = unresolvedFileName ? path.resolve(unresolvedFileName) : ''

const match = file.match(positionRE)
const lineNumber = match && match[1]
const columnNumber = match && match[3]

return {
fileName,
lineNumber,
columnNumber,
}
}
30 changes: 30 additions & 0 deletions packages/launch-editor/parse-file.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const assert = require('node:assert/strict')
const { describe, test } = require('node:test')
const path = require('node:path')

const parseFile = require('./parse-file.js')

describe('launchEditor path resolution', () => {
test('does not resolve an empty file name to the working directory', () => {
assert.equal(parseFile(':1:1').fileName, '')
})

test('resolves relative file names', () => {
assert.deepEqual(parseFile(`.${path.sep}file.js:1:1`), {
fileName: path.resolve('file.js'),
lineNumber: '1',
columnNumber: '1',
})
})

test('resolves a parent-directory component created by a position suffix', () => {
const project = path.resolve('project')
const file = `${project}${path.sep}attacker-controlled${path.sep}..:1:1`

assert.deepEqual(parseFile(file), {
fileName: project,
lineNumber: '1',
columnNumber: '1',
})
})
})
Loading