From d31dc97820d8f17958d9c6de18cd6ffd1947d096 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Mon, 19 Dec 2022 23:54:21 -0500 Subject: [PATCH] Fixes #2207 protects circular JSON.stringify Adds container, commit, branch, tag, and view node protection to the default resolver for @gate & @memoize decorators --- CHANGELOG.md | 1 + src/container.ts | 4 ++++ src/extension.ts | 9 +++---- src/git/models/branch.ts | 5 ++++ src/git/models/commit.ts | 5 ++++ src/git/models/tag.ts | 5 ++++ src/logger.ts | 32 ++++++++++++------------- src/system/decorators/log.ts | 4 ++-- src/system/decorators/resolver.ts | 49 ++++++++++++++++++++++++++++++++------- src/views/nodes/viewNode.ts | 4 ++-- 10 files changed, 82 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b81fbcf..4f9a541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Fixed +- Fixes [#2207](https://github.com/gitkraken/vscode-gitlens/issues/2207) - Error when trying to push individual commit - Fixes [#2301](https://github.com/gitkraken/vscode-gitlens/issues/2301) - Create Worktree button doesn't work in certain cases - Fixes [#2318](https://github.com/gitkraken/vscode-gitlens/issues/2318) - GitLens need to login again after VS Code insiders upgrade every day - Fixes [#2377](https://github.com/gitkraken/vscode-gitlens/issues/2377) - Missing Azure Devops Icon diff --git a/src/container.ts b/src/container.ts index e7663df..75fecf4 100644 --- a/src/container.ts +++ b/src/container.ts @@ -729,3 +729,7 @@ export class Container { }); } } + +export function isContainer(container: any): container is Container { + return container instanceof Container; +} diff --git a/src/extension.ts b/src/extension.ts index 50700a9..43d81aa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,8 +10,9 @@ import { Commands, ContextKeys, CoreCommands } from './constants'; import { Container } from './container'; import { setContext } from './context'; import { isGitUri } from './git/gitUri'; -import { getBranchNameWithoutRemote } from './git/models/branch'; +import { getBranchNameWithoutRemote, isBranch } from './git/models/branch'; import { isCommit } from './git/models/commit'; +import { isTag } from './git/models/tag'; import { Logger, LogLevel } from './logger'; import { showDebugLoggingWarningMessage, @@ -42,11 +43,7 @@ export async function activate(context: ExtensionContext): Promise any>(options?: LogOptions, deb let instanceName: string; if (this != null) { - instanceName = Logger.toLoggableName(this); + instanceName = getLoggableName(this); if (this.constructor?.[LogInstanceNameFn]) { instanceName = target.constructor[LogInstanceNameFn](this, instanceName); } diff --git a/src/system/decorators/resolver.ts b/src/system/decorators/resolver.ts index 6f89058..5eb0221 100644 --- a/src/system/decorators/resolver.ts +++ b/src/system/decorators/resolver.ts @@ -1,9 +1,16 @@ import { Uri } from 'vscode'; +import { isContainer } from '../../container'; +import { isBranch } from '../../git/models/branch'; +import { isCommit } from '../../git/models/commit'; +import { isTag } from '../../git/models/tag'; +import { isViewNode } from '../../views/nodes/viewNode'; function replacer(key: string, value: any): any { if (key === '') return value; if (value == null) return value; + if (typeof value !== 'object') return value; + if (value instanceof Error) return String(value); if (value instanceof Uri) { if ('sha' in (value as any) && (value as any).sha) { @@ -11,6 +18,12 @@ function replacer(key: string, value: any): any { } return value.toString(); } + if (isBranch(value) || isCommit(value) || isTag(value) || isViewNode(value)) { + return value.toString(); + } + if (isContainer(value)) { + return ''; + } return value; } @@ -23,16 +36,34 @@ export function defaultResolver(...args: any[]): string { const arg0 = args[0]; if (arg0 == null) return ''; - if (typeof arg0 === 'string') return arg0; - if (typeof arg0 === 'number' || typeof arg0 === 'boolean' || arg0 instanceof Error) return String(arg0); - if (arg0 instanceof Uri) { - if ('sha' in (arg0 as any) && (arg0 as any).sha) { - return `${(arg0 as any).sha}:${arg0.toString()}`; - } - return arg0.toString(); - } + switch (typeof arg0) { + case 'string': + return arg0; + + case 'number': + case 'boolean': + case 'undefined': + case 'symbol': + case 'bigint': + return String(arg0); - return JSON.stringify(arg0, replacer); + default: + if (arg0 instanceof Error) return String(arg0); + if (arg0 instanceof Uri) { + if ('sha' in arg0 && typeof arg0.sha === 'string' && arg0.sha) { + return `${arg0.sha}:${arg0.toString()}`; + } + return arg0.toString(); + } + if (isBranch(arg0) || isCommit(arg0) || isTag(arg0) || isViewNode(arg0)) { + return arg0.toString(); + } + if (isContainer(arg0)) { + return ''; + } + + return JSON.stringify(arg0, replacer); + } } export type Resolver any> = (...args: Parameters) => string; diff --git a/src/views/nodes/viewNode.ts b/src/views/nodes/viewNode.ts index 96a4117..83a112e 100644 --- a/src/views/nodes/viewNode.ts +++ b/src/views/nodes/viewNode.ts @@ -10,7 +10,7 @@ import { GitReference } from '../../git/models/reference'; import { GitRemote } from '../../git/models/remote'; import type { RepositoryChangeEvent } from '../../git/models/repository'; import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '../../git/models/repository'; -import { Logger } from '../../logger'; +import { getLoggableName } from '../../logger'; import type { SubscriptionChangeEvent } from '../../plus/subscription/subscriptionService'; import { gate } from '../../system/decorators/gate'; import { debug, log, logName } from '../../system/decorators/log'; @@ -96,7 +96,7 @@ export abstract class ViewNode