From de5c4b8702ae64a957c294bb35638099bdb785a6 Mon Sep 17 00:00:00 2001
From: RahulGautamSingh <rahul_ug@cse.nits.ac.in>
Date: Tue, 21 Dec 2021 22:28:50 +0530
Subject: [PATCH] refactor(semver): ensure strict null check (#13161)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---
 lib/versioning/semver-coerced/index.spec.ts |  8 +++-
 lib/versioning/semver-coerced/index.ts      | 47 ++++++++++++++-------
 lib/versioning/semver/index.ts              |  3 +-
 tsconfig.strict.json                        |  2 +
 4 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/lib/versioning/semver-coerced/index.spec.ts b/lib/versioning/semver-coerced/index.spec.ts
index 25fdee12ad..2741806679 100644
--- a/lib/versioning/semver-coerced/index.spec.ts
+++ b/lib/versioning/semver-coerced/index.spec.ts
@@ -68,15 +68,19 @@ describe('versioning/semver-coerced/index', () => {
     it('should return false for lower version in strict semver', () => {
       expect(semverCoerced.isGreaterThan('3.1.2', '4.1.0')).toBeFalsy();
     });
+
+    it('should return false if version cannot be coerced', () => {
+      expect(semverCoerced.isGreaterThan('e.e.e', '4.1.0')).toBeFalsy();
+    });
   });
 
   describe('.isLessThanRange(version, range)', () => {
     it('should return true for a lower version in strict semver', () => {
-      expect(semverCoerced.isLessThanRange('1.0.2', '~2.0')).toBeTruthy();
+      expect(semverCoerced.isLessThanRange?.('1.0.2', '~2.0')).toBeTruthy();
     });
 
     it('should return false for in-range version in strict semver', () => {
-      expect(semverCoerced.isLessThanRange('3.0.2', '~3.0')).toBeFalsy();
+      expect(semverCoerced.isLessThanRange?.('3.0.2', '~3.0')).toBeFalsy();
     });
   });
 
diff --git a/lib/versioning/semver-coerced/index.ts b/lib/versioning/semver-coerced/index.ts
index 9806270592..941f276e7a 100644
--- a/lib/versioning/semver-coerced/index.ts
+++ b/lib/versioning/semver-coerced/index.ts
@@ -1,3 +1,4 @@
+import is from '@sindresorhus/is';
 import semver, { SemVer } from 'semver';
 import stable from 'semver-stable';
 import { regEx } from '../../util/regex';
@@ -11,15 +12,20 @@ export const supportsRanges = false;
 const { is: isStable } = stable;
 
 function sortVersions(a: string, b: string): number {
-  return semver.compare(semver.coerce(a), semver.coerce(b));
+  const aCoerced = semver.coerce(a);
+  const bCoerced = semver.coerce(b);
+
+  return aCoerced && bCoerced ? semver.compare(aCoerced, bCoerced) : 0;
 }
 
 function getMajor(a: string | SemVer): number | null {
-  return semver.major(semver.coerce(a));
+  const aCoerced = semver.coerce(a);
+  return aCoerced ? semver.major(aCoerced) : null;
 }
 
 function getMinor(a: string | SemVer): number | null {
-  return semver.minor(semver.coerce(a));
+  const aCoerced = semver.coerce(a);
+  return aCoerced ? semver.minor(aCoerced) : null;
 }
 
 function getPatch(a: string | SemVer): number | null {
@@ -27,11 +33,14 @@ function getPatch(a: string | SemVer): number | null {
 }
 
 function matches(version: string, range: string): boolean {
-  return semver.satisfies(semver.coerce(version), range);
+  const coercedVersion = semver.coerce(version);
+  return coercedVersion ? semver.satisfies(coercedVersion, range) : false;
 }
 
 function equals(a: string, b: string): boolean {
-  return semver.eq(semver.coerce(a), semver.coerce(b));
+  const aCoerced = semver.coerce(a);
+  const bCoerced = semver.coerce(b);
+  return aCoerced && bCoerced ? semver.eq(aCoerced, bCoerced) : false;
 }
 
 function isValid(version: string): string | boolean | null {
@@ -42,10 +51,10 @@ function getSatisfyingVersion(
   versions: string[],
   range: string
 ): string | null {
-  const coercedVersions = versions.map((version) => {
-    const coercedVersion = semver.coerce(version);
-    return coercedVersion ? coercedVersion.version : null;
-  });
+  const coercedVersions = versions
+    .map((version) => semver.coerce(version)?.version)
+    .filter(is.string);
+
   return semver.maxSatisfying(coercedVersions, range);
 }
 
@@ -53,19 +62,24 @@ function minSatisfyingVersion(
   versions: string[],
   range: string
 ): string | null {
-  const coercedVersions = versions.map((version) => {
-    const coercedVersion = semver.coerce(version);
-    return coercedVersion ? coercedVersion.version : null;
-  });
+  const coercedVersions = versions
+    .map((version) => semver.coerce(version)?.version)
+    .filter(is.string);
+
   return semver.minSatisfying(coercedVersions, range);
 }
 
 function isLessThanRange(version: string, range: string): boolean {
-  return semver.ltr(semver.coerce(version), range);
+  const coercedVersion = semver.coerce(version);
+  return coercedVersion ? semver.ltr(coercedVersion, range) : false;
 }
 
 function isGreaterThan(version: string, other: string): boolean {
-  return semver.gt(semver.coerce(version), semver.coerce(other));
+  const coercedVersion = semver.coerce(version);
+  const coercedOther = semver.coerce(other);
+  return coercedVersion && coercedOther
+    ? semver.gt(coercedVersion, coercedOther)
+    : false;
 }
 
 const startsWithNumberRegex = regEx(`^\\d`);
@@ -81,7 +95,8 @@ function isSingleVersion(version: string): string | boolean | null {
 }
 
 // If this is left as an alias, inputs like "17.04.0" throw errors
-export const isVersion = (input: string): string | boolean => isValid(input);
+export const isVersion = (input: string): string | boolean | null =>
+  isValid(input);
 
 export { isVersion as isValid, getSatisfyingVersion };
 
diff --git a/lib/versioning/semver/index.ts b/lib/versioning/semver/index.ts
index 76ee0b6b53..dc9f8485b3 100644
--- a/lib/versioning/semver/index.ts
+++ b/lib/versioning/semver/index.ts
@@ -24,7 +24,8 @@ const {
 } = semver;
 
 // If this is left as an alias, inputs like "17.04.0" throw errors
-export const isVersion = (input: string): string => valid(input);
+export const isVersion = (input: string): string | boolean | null =>
+  valid(input);
 
 export { isVersion as isValid, getSatisfyingVersion };
 
diff --git a/tsconfig.strict.json b/tsconfig.strict.json
index 9076ab5e2e..8fd3ec0ec6 100644
--- a/tsconfig.strict.json
+++ b/tsconfig.strict.json
@@ -46,6 +46,8 @@
     "lib/util/url.ts",
     "lib/versioning/swift/*.ts",
     "lib/versioning/ubuntu/*.ts",
+    "lib/versioning/semver/*.ts",
+    "lib/versioning/semver-coerced/*.ts",
     "lib/workers/pr/changelog/hbs-template.ts",
     "lib/workers/pr/changelog/types.ts",
     "lib/workers/repository/init/types.ts",
-- 
GitLab