Skip to content

Commit 875e5a9

Browse files
authored
Merge pull request microsoft#15378 from karthiknadig/cherry1
Cherry picked fixes from main
2 parents 7352a0a + ca8cbdf commit 875e5a9

File tree

29 files changed

+678
-364
lines changed

29 files changed

+678
-364
lines changed

.eslintignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ src/test/common/terminals/service.unit.test.ts
186186
src/test/common/terminals/helper.unit.test.ts
187187
src/test/common/terminals/activation.unit.test.ts
188188
src/test/common/terminals/shellDetectors/shellDetectors.unit.test.ts
189-
src/test/common/terminals/environmentActivationProviders/pipEnvActivationProvider.unit.test.ts
190189
src/test/common/terminals/environmentActivationProviders/terminalActivation.testvirtualenvs.ts
191190
src/test/common/socketStream.test.ts
192191
src/test/common/configSettings.test.ts
@@ -210,8 +209,6 @@ src/test/common/featureDeprecationManager.unit.test.ts
210209
src/test/common/serviceRegistry.unit.test.ts
211210
src/test/common/extensions.unit.test.ts
212211
src/test/common/variables/envVarsService.unit.test.ts
213-
src/test/common/variables/environmentVariablesProvider.unit.test.ts
214-
src/test/common/variables/envVarsProvider.multiroot.test.ts
215212
src/test/common/nuget/azureBobStoreRepository.unit.test.ts
216213
src/test/common/helpers.test.ts
217214
src/test/common/application/commands/reloadCommand.unit.test.ts
@@ -383,7 +380,6 @@ src/client/providers/docStringFoldingProvider.ts
383380
src/client/providers/linterProvider.ts
384381
src/client/providers/simpleRefactorProvider.ts
385382
src/client/providers/completionProvider.ts
386-
src/client/providers/jediProxy.ts
387383
src/client/providers/definitionProvider.ts
388384
src/client/providers/referenceProvider.ts
389385
src/client/providers/terminalProvider.ts
@@ -549,7 +545,6 @@ src/client/common/terminal/shellDetectors/vscEnvironmentShellDetector.ts
549545
src/client/common/terminal/shellDetectors/terminalNameShellDetector.ts
550546
src/client/common/terminal/shellDetectors/settingsShellDetector.ts
551547
src/client/common/terminal/shellDetectors/baseShellDetector.ts
552-
src/client/common/terminal/environmentActivationProviders/pipEnvActivationProvider.ts
553548
src/client/common/terminal/environmentActivationProviders/baseActivationProvider.ts
554549
src/client/common/terminal/environmentActivationProviders/commandPrompt.ts
555550
src/client/common/terminal/environmentActivationProviders/bash.ts
@@ -578,7 +573,6 @@ src/client/common/constants.ts
578573
src/client/common/variables/serviceRegistry.ts
579574
src/client/common/variables/environment.ts
580575
src/client/common/variables/types.ts
581-
src/client/common/variables/environmentVariablesProvider.ts
582576
src/client/common/variables/sysTypes.ts
583577
src/client/common/variables/systemVariables.ts
584578
src/client/common/nuget/azureBlobStoreNugetRepository.ts

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,8 @@ part of!
653653
([#14182](https://github.com/Microsoft/vscode-python/issues/14182))
654654
1. Fix exporting from the interactive window.
655655
([#14210](https://github.com/Microsoft/vscode-python/issues/14210))
656+
1. Fix for CVE-2020-16977
657+
([CVE-2020-16977](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-16977))
656658

657659
### Thanks
658660

news/2 Fixes/15364.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow support for using notebook APIs in the VS code stable build.

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,6 @@
10441044
"DeprecatePythonPath - experiment",
10451045
"RunByLine - experiment",
10461046
"tryPylance",
1047-
"jediLSP",
10481047
"debuggerDataViewer",
10491048
"pythonSendEntireLineToREPL",
10501049
"pythonTensorboardExperiment",
@@ -1074,7 +1073,6 @@
10741073
"DeprecatePythonPath - experiment",
10751074
"RunByLine - experiment",
10761075
"tryPylance",
1077-
"jediLSP",
10781076
"debuggerDataViewer",
10791077
"pythonSendEntireLineToREPL",
10801078
"pythonTensorboardExperiment",

src/client/activation/jedi/analysisOptions.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,61 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33
import { inject, injectable } from 'inversify';
4+
import * as path from 'path';
5+
import { WorkspaceFolder } from 'vscode';
6+
import { IWorkspaceService } from '../../common/application/types';
7+
import { IConfigurationService, Resource } from '../../common/types';
48

59
import { IEnvironmentVariablesProvider } from '../../common/variables/types';
10+
import { PythonEnvironment } from '../../pythonEnvironments/info';
611
import { LanguageServerAnalysisOptionsWithEnv } from '../common/analysisOptions';
712
import { ILanguageServerOutputChannel } from '../types';
813

914
/* eslint-disable @typescript-eslint/explicit-module-boundary-types, class-methods-use-this */
1015

1116
@injectable()
1217
export class JediLanguageServerAnalysisOptions extends LanguageServerAnalysisOptionsWithEnv {
13-
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
18+
private resource: Resource | undefined;
19+
1420
constructor(
1521
@inject(IEnvironmentVariablesProvider) envVarsProvider: IEnvironmentVariablesProvider,
1622
@inject(ILanguageServerOutputChannel) lsOutputChannel: ILanguageServerOutputChannel,
23+
@inject(IConfigurationService) private readonly configurationService: IConfigurationService,
24+
@inject(IWorkspaceService) private readonly workspace: IWorkspaceService,
1725
) {
1826
super(envVarsProvider, lsOutputChannel);
27+
this.resource = undefined;
28+
}
29+
30+
public async initialize(resource: Resource, interpreter: PythonEnvironment | undefined) {
31+
this.resource = resource;
32+
return super.initialize(resource, interpreter);
33+
}
34+
35+
protected getWorkspaceFolder(): WorkspaceFolder | undefined {
36+
return this.workspace.getWorkspaceFolder(this.resource);
1937
}
2038

2139
protected async getInitializationOptions() {
40+
const pythonSettings = this.configurationService.getSettings(this.resource);
41+
const workspacePath = this.getWorkspaceFolder()?.uri.fsPath;
42+
const extraPaths = pythonSettings.autoComplete
43+
? pythonSettings.autoComplete.extraPaths.map((extraPath) => {
44+
if (path.isAbsolute(extraPath)) {
45+
return extraPath;
46+
}
47+
return workspacePath ? path.join(workspacePath, extraPath) : '';
48+
})
49+
: [];
50+
51+
if (workspacePath) {
52+
extraPaths.unshift(workspacePath);
53+
}
54+
55+
const distinctExtraPaths = extraPaths
56+
.filter((value) => value.length > 0)
57+
.filter((value, index, self) => self.indexOf(value) === index);
58+
2259
return {
2360
markupKindPreferred: 'markdown',
2461
completion: {
@@ -31,6 +68,9 @@ export class JediLanguageServerAnalysisOptions extends LanguageServerAnalysisOpt
3168
didSave: true,
3269
didChange: true,
3370
},
71+
workspace: {
72+
extraPaths: distinctExtraPaths,
73+
},
3474
};
3575
}
3676
}

src/client/common/process/proc.ts

Lines changed: 7 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
3-
import { exec, execSync, spawn } from 'child_process';
43
import { EventEmitter } from 'events';
5-
import { Observable } from 'rxjs/Observable';
6-
import { Readable } from 'stream';
74

85
import { IDisposable } from '../types';
9-
import { createDeferred } from '../utils/async';
106
import { EnvironmentVariables } from '../variables/types';
11-
import { DEFAULT_ENCODING } from './constants';
7+
import { execObservable, killPid, plainExec, shellExec } from './rawProcessApis';
128
import {
139
ExecutionResult,
1410
IBufferDecoder,
1511
IProcessService,
1612
ObservableExecutionResult,
17-
Output,
1813
ShellOptions,
1914
SpawnOptions,
20-
StdErrError,
2115
} from './types';
2216

2317
export class ProcessService extends EventEmitter implements IProcessService {
@@ -37,16 +31,7 @@ export class ProcessService extends EventEmitter implements IProcessService {
3731
}
3832

3933
public static kill(pid: number): void {
40-
try {
41-
if (process.platform === 'win32') {
42-
// Windows doesn't support SIGTERM, so execute taskkill to kill the process
43-
execSync(`taskkill /pid ${pid} /T /F`); // NOSONAR
44-
} else {
45-
process.kill(pid);
46-
}
47-
} catch {
48-
// Ignore.
49-
}
34+
killPid(pid);
5035
}
5136

5237
public dispose(): void {
@@ -61,199 +46,18 @@ export class ProcessService extends EventEmitter implements IProcessService {
6146
}
6247

6348
public execObservable(file: string, args: string[], options: SpawnOptions = {}): ObservableExecutionResult<string> {
64-
const spawnOptions = this.getDefaultOptions(options);
65-
const encoding = spawnOptions.encoding ? spawnOptions.encoding : 'utf8';
66-
const proc = spawn(file, args, spawnOptions);
67-
let procExited = false;
68-
const disposable: IDisposable = {
69-
dispose() {
70-
if (proc && !proc.killed && !procExited) {
71-
ProcessService.kill(proc.pid);
72-
}
73-
if (proc) {
74-
proc.unref();
75-
}
76-
},
77-
};
78-
this.processesToKill.add(disposable);
79-
80-
const output = new Observable<Output<string>>((subscriber) => {
81-
const disposables: IDisposable[] = [];
82-
83-
// eslint-disable-next-line @typescript-eslint/ban-types
84-
const on = (ee: Readable | null, name: string, fn: Function) => {
85-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
86-
ee?.on(name, fn as any);
87-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
88-
disposables.push({ dispose: () => ee?.removeListener(name, fn as any) as any });
89-
};
90-
91-
if (options.token) {
92-
disposables.push(
93-
options.token.onCancellationRequested(() => {
94-
if (!procExited && !proc.killed) {
95-
proc.kill();
96-
procExited = true;
97-
}
98-
}),
99-
);
100-
}
101-
102-
const sendOutput = (source: 'stdout' | 'stderr', data: Buffer) => {
103-
const out = this.decoder.decode([data], encoding);
104-
if (source === 'stderr' && options.throwOnStdErr) {
105-
subscriber.error(new StdErrError(out));
106-
} else {
107-
subscriber.next({ source, out });
108-
}
109-
};
110-
111-
on(proc.stdout, 'data', (data: Buffer) => sendOutput('stdout', data));
112-
on(proc.stderr, 'data', (data: Buffer) => sendOutput('stderr', data));
113-
114-
proc.once('close', () => {
115-
procExited = true;
116-
subscriber.complete();
117-
disposables.forEach((d) => d.dispose());
118-
});
119-
proc.once('exit', () => {
120-
procExited = true;
121-
subscriber.complete();
122-
disposables.forEach((d) => d.dispose());
123-
});
124-
proc.once('error', (ex) => {
125-
procExited = true;
126-
subscriber.error(ex);
127-
disposables.forEach((d) => d.dispose());
128-
});
129-
});
130-
49+
const result = execObservable(file, args, options, this.decoder, this.env, this.processesToKill);
13150
this.emit('exec', file, args, options);
132-
133-
return {
134-
proc,
135-
out: output,
136-
dispose: disposable.dispose,
137-
};
51+
return result;
13852
}
13953

14054
public exec(file: string, args: string[], options: SpawnOptions = {}): Promise<ExecutionResult<string>> {
141-
const spawnOptions = this.getDefaultOptions(options);
142-
const encoding = spawnOptions.encoding ? spawnOptions.encoding : 'utf8';
143-
const proc = spawn(file, args, spawnOptions);
144-
const deferred = createDeferred<ExecutionResult<string>>();
145-
const disposable: IDisposable = {
146-
dispose: () => {
147-
if (!proc.killed && !deferred.completed) {
148-
proc.kill();
149-
}
150-
},
151-
};
152-
this.processesToKill.add(disposable);
153-
const disposables: IDisposable[] = [];
154-
155-
// eslint-disable-next-line @typescript-eslint/ban-types
156-
const on = (ee: Readable | null, name: string, fn: Function) => {
157-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
158-
ee?.on(name, fn as any);
159-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
160-
disposables.push({ dispose: () => ee?.removeListener(name, fn as any) as any });
161-
};
162-
163-
if (options.token) {
164-
disposables.push(options.token.onCancellationRequested(disposable.dispose));
165-
}
166-
167-
const stdoutBuffers: Buffer[] = [];
168-
on(proc.stdout, 'data', (data: Buffer) => stdoutBuffers.push(data));
169-
const stderrBuffers: Buffer[] = [];
170-
on(proc.stderr, 'data', (data: Buffer) => {
171-
if (options.mergeStdOutErr) {
172-
stdoutBuffers.push(data);
173-
stderrBuffers.push(data);
174-
} else {
175-
stderrBuffers.push(data);
176-
}
177-
});
178-
179-
proc.once('close', () => {
180-
if (deferred.completed) {
181-
return;
182-
}
183-
const stderr: string | undefined =
184-
stderrBuffers.length === 0 ? undefined : this.decoder.decode(stderrBuffers, encoding);
185-
if (stderr && stderr.length > 0 && options.throwOnStdErr) {
186-
deferred.reject(new StdErrError(stderr));
187-
} else {
188-
const stdout = this.decoder.decode(stdoutBuffers, encoding);
189-
deferred.resolve({ stdout, stderr });
190-
}
191-
disposables.forEach((d) => d.dispose());
192-
});
193-
proc.once('error', (ex) => {
194-
deferred.reject(ex);
195-
disposables.forEach((d) => d.dispose());
196-
});
197-
55+
const promise = plainExec(file, args, options, this.decoder, this.env, this.processesToKill);
19856
this.emit('exec', file, args, options);
199-
200-
return deferred.promise;
57+
return promise;
20158
}
20259

20360
public shellExec(command: string, options: ShellOptions = {}): Promise<ExecutionResult<string>> {
204-
const shellOptions = this.getDefaultOptions(options);
205-
return new Promise((resolve, reject) => {
206-
const proc = exec(command, shellOptions, (e, stdout, stderr) => {
207-
if (e && e !== null) {
208-
reject(e);
209-
} else if (shellOptions.throwOnStdErr && stderr && stderr.length) {
210-
reject(new Error(stderr));
211-
} else {
212-
// Make sure stderr is undefined if we actually had none. This is checked
213-
// elsewhere because that's how exec behaves.
214-
resolve({ stderr: stderr && stderr.length > 0 ? stderr : undefined, stdout });
215-
}
216-
}); // NOSONAR
217-
const disposable: IDisposable = {
218-
dispose: () => {
219-
if (!proc.killed) {
220-
proc.kill();
221-
}
222-
},
223-
};
224-
this.processesToKill.add(disposable);
225-
});
226-
}
227-
228-
private getDefaultOptions<T extends ShellOptions | SpawnOptions>(options: T): T {
229-
const defaultOptions = { ...options };
230-
const execOptions = defaultOptions as SpawnOptions;
231-
if (execOptions) {
232-
execOptions.encoding =
233-
typeof execOptions.encoding === 'string' && execOptions.encoding.length > 0
234-
? execOptions.encoding
235-
: DEFAULT_ENCODING;
236-
const { encoding } = execOptions;
237-
delete execOptions.encoding;
238-
execOptions.encoding = encoding;
239-
}
240-
if (!defaultOptions.env || Object.keys(defaultOptions.env).length === 0) {
241-
const env = this.env ? this.env : process.env;
242-
defaultOptions.env = { ...env };
243-
} else {
244-
defaultOptions.env = { ...defaultOptions.env };
245-
}
246-
247-
if (execOptions && execOptions.extraVariables) {
248-
defaultOptions.env = { ...defaultOptions.env, ...execOptions.extraVariables };
249-
}
250-
251-
// Always ensure we have unbuffered output.
252-
defaultOptions.env.PYTHONUNBUFFERED = '1';
253-
if (!defaultOptions.env.PYTHONIOENCODING) {
254-
defaultOptions.env.PYTHONIOENCODING = 'utf-8';
255-
}
256-
257-
return defaultOptions;
61+
return shellExec(command, options, this.env, this.processesToKill);
25862
}
25963
}

0 commit comments

Comments
 (0)