Skip to content

Commit ea80edc

Browse files
authored
fix: CN-482 use correct falsy checks (#726)
* fix: correctly check for existence, add tests for that * fix: order imports alphabetically * fix: linting * fix: use correct url parsed strings to check for versions * fix: update dependent snapshots * fix: disable containerd when generating snapshots
1 parent 45e1996 commit ea80edc

File tree

4 files changed

+220
-12
lines changed

4 files changed

+220
-12
lines changed

lib/analyzer/package-managers/rpm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function purl(
6060
qualifiers.repositories = repos.join(",");
6161
}
6262

63-
if (pkg.epoch) {
63+
if (pkg.epoch !== undefined && pkg.epoch !== null) {
6464
qualifiers.epoch = String(pkg.epoch);
6565
}
6666

test/lib/analyzer/package-managers/rpm.spec.ts

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,216 @@
1+
import { PackageInfo } from "@snyk/rpm-parser/lib/rpm/types";
12
import * as fs from "fs";
23
import * as path from "path";
3-
import { parseSourceRPM } from "../../../../lib/analyzer/package-managers/rpm";
4+
import {
5+
analyze,
6+
mapRpmSqlitePackages,
7+
parseSourceRPM,
8+
} from "../../../../lib/analyzer/package-managers/rpm";
49
import { SourcePackage } from "../../../../lib/analyzer/types";
510

11+
describe("RPM Package Version and Epoch Handling", () => {
12+
describe("formats version without epoch", () => {
13+
it("should format version string correctly", () => {
14+
const mappedResults = mapRpmSqlitePackages(
15+
"test-image",
16+
[
17+
{
18+
name: "bash",
19+
version: "5.1.16",
20+
release: "4.el9",
21+
size: 1024,
22+
},
23+
],
24+
[],
25+
);
26+
27+
expect(mappedResults.Analysis).toHaveLength(1);
28+
expect(mappedResults.Analysis[0].Name).toBe("bash");
29+
expect(mappedResults.Analysis[0].Version).toBe("5.1.16-4.el9");
30+
expect(mappedResults.Analysis[0].Purl).toBe("pkg:rpm/bash@5.1.16-4.el9");
31+
});
32+
});
33+
34+
describe("formats version with epoch == 0", () => {
35+
it("should include epoch=0 in PURL qualifier (bug fix)", () => {
36+
const mappedResults = mapRpmSqlitePackages(
37+
"test-image",
38+
[
39+
{
40+
name: "libarchive",
41+
version: "3.7.7",
42+
release: "4.el10_0",
43+
epoch: 0,
44+
size: 2048,
45+
},
46+
],
47+
[],
48+
);
49+
50+
expect(mappedResults.Analysis).toHaveLength(1);
51+
expect(mappedResults.Analysis[0].Name).toBe("libarchive");
52+
expect(mappedResults.Analysis[0].Version).toBe("3.7.7-4.el10_0");
53+
// Critical: epoch=0 must be explicitly included in PURL
54+
expect(mappedResults.Analysis[0].Purl).toBe(
55+
"pkg:rpm/libarchive@3.7.7-4.el10_0?epoch=0",
56+
);
57+
});
58+
59+
it("should include epoch=0 with distro qualifier", () => {
60+
const mappedResults = mapRpmSqlitePackages(
61+
"test-image",
62+
[
63+
{
64+
name: "sqlite-libs",
65+
version: "3.34.1",
66+
release: "5.el8",
67+
epoch: 0,
68+
size: 1500,
69+
},
70+
],
71+
[],
72+
{ name: "rhel", version: "8.5" },
73+
);
74+
75+
expect(mappedResults.Analysis[0].Purl).toBe(
76+
"pkg:rpm/rhel/sqlite-libs@3.34.1-5.el8?distro=rhel-8.5&epoch=0",
77+
);
78+
});
79+
});
80+
81+
describe("formats version with non-zero epoch", () => {
82+
it("should format version with epoch=1", () => {
83+
const mappedResults = mapRpmSqlitePackages(
84+
"test-image",
85+
[
86+
{
87+
name: "findutils",
88+
version: "4.5.11",
89+
release: "6.amzn2",
90+
epoch: 1,
91+
size: 3000,
92+
},
93+
],
94+
[],
95+
);
96+
97+
expect(mappedResults.Analysis[0].Name).toBe("findutils");
98+
expect(mappedResults.Analysis[0].Version).toBe("1:4.5.11-6.amzn2");
99+
expect(mappedResults.Analysis[0].Purl).toBe(
100+
"pkg:rpm/findutils@1:4.5.11-6.amzn2?epoch=1",
101+
);
102+
});
103+
});
104+
105+
describe("epoch consistency across functions", () => {
106+
it("should handle epoch=0 consistently in analyze() function", async () => {
107+
const pkgs: PackageInfo[] = [
108+
{
109+
name: "openssl-libs",
110+
version: "1.1.1",
111+
release: "15.el8",
112+
epoch: 0,
113+
size: 6000,
114+
},
115+
];
116+
117+
const result = await analyze("test-image", pkgs, [], {
118+
name: "rhel",
119+
version: "8.2",
120+
});
121+
122+
expect(result.Analysis[0].Purl).toBe(
123+
"pkg:rpm/rhel/openssl-libs@1.1.1-15.el8?distro=rhel-8.2&epoch=0",
124+
);
125+
});
126+
});
127+
128+
describe("multiple packages with different epochs", () => {
129+
it("should correctly handle mixed epoch values", () => {
130+
const packages: PackageInfo[] = [
131+
{
132+
name: "pkg-no-epoch",
133+
version: "1.0.0",
134+
release: "1",
135+
size: 100,
136+
},
137+
{
138+
name: "pkg-epoch-zero",
139+
version: "2.0.0",
140+
release: "1",
141+
epoch: 0,
142+
size: 200,
143+
},
144+
{
145+
name: "pkg-epoch-one",
146+
version: "3.0.0",
147+
release: "1",
148+
epoch: 1,
149+
size: 300,
150+
},
151+
];
152+
153+
const result = mapRpmSqlitePackages("test-image", packages, []);
154+
155+
expect(result.Analysis[0].Purl).toBe("pkg:rpm/pkg-no-epoch@1.0.0-1");
156+
expect(result.Analysis[1].Purl).toBe(
157+
"pkg:rpm/pkg-epoch-zero@2.0.0-1?epoch=0",
158+
);
159+
expect(result.Analysis[2].Purl).toBe(
160+
"pkg:rpm/pkg-epoch-one@1:3.0.0-1?epoch=1",
161+
);
162+
});
163+
});
164+
165+
describe("epoch with repositories and modules", () => {
166+
it("should include epoch with other qualifiers", () => {
167+
const result = mapRpmSqlitePackages(
168+
"test-image",
169+
[
170+
{
171+
name: "nodejs",
172+
version: "10.21.0",
173+
release: "3.module+el8.2.0",
174+
epoch: 1,
175+
module: "nodejs:10",
176+
size: 7000,
177+
},
178+
],
179+
["rhel-8-appstream"],
180+
{ name: "rhel", version: "8.2" },
181+
);
182+
183+
const purl = result.Analysis[0].Purl;
184+
expect(purl).toContain("?");
185+
expect(purl).toContain("epoch=1");
186+
expect(purl).toContain("module=nodejs%3A10"); // : is URL-encoded as %3A
187+
expect(purl).toContain("repositories=rhel-8-appstream");
188+
expect(purl).toContain("distro=rhel-8.2");
189+
});
190+
191+
it("should include epoch=0 with sourceRPM upstream qualifier", () => {
192+
const result = mapRpmSqlitePackages(
193+
"test-image",
194+
[
195+
{
196+
name: "libxml2",
197+
version: "2.9.7",
198+
release: "14.el8",
199+
epoch: 0,
200+
sourceRPM: "libxml2-2.9.7-14.el8.src.rpm",
201+
size: 8000,
202+
},
203+
],
204+
[],
205+
);
206+
207+
const purl = result.Analysis[0].Purl;
208+
expect(purl).toContain("epoch=0");
209+
expect(purl).toContain("upstream=libxml2%402.9.7"); // @ is URL-encoded as %40
210+
});
211+
});
212+
});
213+
6214
describe("parseSourceRPM", () => {
7215
it("should correctly parse all valid source RPM strings from source_rpms.csv", () => {
8216
const csvFilePath = path.join(

test/system/operating-systems/__snapshots__/centos6.spec.ts.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2662,15 +2662,15 @@ Object {
26622662
"id": "perl-CGI@3.51-144.el6",
26632663
"info": Object {
26642664
"name": "perl-CGI",
2665-
"purl": "pkg:rpm/centos/perl-CGI@3.51-144.el6?distro=centos-6&upstream=perl%405.10.1",
2665+
"purl": "pkg:rpm/centos/perl-CGI@3.51-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
26662666
"version": "3.51-144.el6",
26672667
},
26682668
},
26692669
Object {
26702670
"id": "perl-ExtUtils-MakeMaker@6.55-144.el6",
26712671
"info": Object {
26722672
"name": "perl-ExtUtils-MakeMaker",
2673-
"purl": "pkg:rpm/centos/perl-ExtUtils-MakeMaker@6.55-144.el6?distro=centos-6&upstream=perl%405.10.1",
2673+
"purl": "pkg:rpm/centos/perl-ExtUtils-MakeMaker@6.55-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
26742674
"version": "6.55-144.el6",
26752675
},
26762676
},
@@ -2710,15 +2710,15 @@ Object {
27102710
"id": "perl-Test-Harness@3.17-144.el6",
27112711
"info": Object {
27122712
"name": "perl-Test-Harness",
2713-
"purl": "pkg:rpm/centos/perl-Test-Harness@3.17-144.el6?distro=centos-6&upstream=perl%405.10.1",
2713+
"purl": "pkg:rpm/centos/perl-Test-Harness@3.17-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
27142714
"version": "3.17-144.el6",
27152715
},
27162716
},
27172717
Object {
27182718
"id": "perl-Test-Simple@0.92-144.el6",
27192719
"info": Object {
27202720
"name": "perl-Test-Simple",
2721-
"purl": "pkg:rpm/centos/perl-Test-Simple@0.92-144.el6?distro=centos-6&upstream=perl%405.10.1",
2721+
"purl": "pkg:rpm/centos/perl-Test-Simple@0.92-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
27222722
"version": "0.92-144.el6",
27232723
},
27242724
},
@@ -5902,15 +5902,15 @@ Object {
59025902
"id": "perl-CGI@3.51-144.el6",
59035903
"info": Object {
59045904
"name": "perl-CGI",
5905-
"purl": "pkg:rpm/centos/perl-CGI@3.51-144.el6?distro=centos-6&upstream=perl%405.10.1",
5905+
"purl": "pkg:rpm/centos/perl-CGI@3.51-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
59065906
"version": "3.51-144.el6",
59075907
},
59085908
},
59095909
Object {
59105910
"id": "perl-ExtUtils-MakeMaker@6.55-144.el6",
59115911
"info": Object {
59125912
"name": "perl-ExtUtils-MakeMaker",
5913-
"purl": "pkg:rpm/centos/perl-ExtUtils-MakeMaker@6.55-144.el6?distro=centos-6&upstream=perl%405.10.1",
5913+
"purl": "pkg:rpm/centos/perl-ExtUtils-MakeMaker@6.55-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
59145914
"version": "6.55-144.el6",
59155915
},
59165916
},
@@ -5950,15 +5950,15 @@ Object {
59505950
"id": "perl-Test-Harness@3.17-144.el6",
59515951
"info": Object {
59525952
"name": "perl-Test-Harness",
5953-
"purl": "pkg:rpm/centos/perl-Test-Harness@3.17-144.el6?distro=centos-6&upstream=perl%405.10.1",
5953+
"purl": "pkg:rpm/centos/perl-Test-Harness@3.17-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
59545954
"version": "3.17-144.el6",
59555955
},
59565956
},
59575957
Object {
59585958
"id": "perl-Test-Simple@0.92-144.el6",
59595959
"info": Object {
59605960
"name": "perl-Test-Simple",
5961-
"purl": "pkg:rpm/centos/perl-Test-Simple@0.92-144.el6?distro=centos-6&upstream=perl%405.10.1",
5961+
"purl": "pkg:rpm/centos/perl-Test-Simple@0.92-144.el6?distro=centos-6&epoch=0&upstream=perl%405.10.1",
59625962
"version": "0.92-144.el6",
59635963
},
59645964
},

test/system/operating-systems/__snapshots__/ubi8.spec.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5110,7 +5110,7 @@ Object {
51105110
"id": "perl-Errno@1.28-416.el8",
51115111
"info": Object {
51125112
"name": "perl-Errno",
5113-
"purl": "pkg:rpm/rhel/perl-Errno@1.28-416.el8?distro=rhel-8.2&repositories=rhel-8-for-x86_64-baseos-rpms%2Crhel-8-for-x86_64-appstream-rpms%2Crhel-8-for-x86_64-baseos-beta-rpms%2Crhel-8-for-x86_64-appstream-beta-rpms%2Crhel-8-for-x86_64-baseos-htb-rpms%2Crhel-8-for-x86_64-appstream-htb-rpms&upstream=perl%405.26.3",
5113+
"purl": "pkg:rpm/rhel/perl-Errno@1.28-416.el8?distro=rhel-8.2&epoch=0&repositories=rhel-8-for-x86_64-baseos-rpms%2Crhel-8-for-x86_64-appstream-rpms%2Crhel-8-for-x86_64-baseos-beta-rpms%2Crhel-8-for-x86_64-appstream-beta-rpms%2Crhel-8-for-x86_64-baseos-htb-rpms%2Crhel-8-for-x86_64-appstream-htb-rpms&upstream=perl%405.26.3",
51145114
"version": "1.28-416.el8",
51155115
},
51165116
},
@@ -5174,7 +5174,7 @@ Object {
51745174
"id": "perl-IO@1.38-416.el8",
51755175
"info": Object {
51765176
"name": "perl-IO",
5177-
"purl": "pkg:rpm/rhel/perl-IO@1.38-416.el8?distro=rhel-8.2&repositories=rhel-8-for-x86_64-baseos-rpms%2Crhel-8-for-x86_64-appstream-rpms%2Crhel-8-for-x86_64-baseos-beta-rpms%2Crhel-8-for-x86_64-appstream-beta-rpms%2Crhel-8-for-x86_64-baseos-htb-rpms%2Crhel-8-for-x86_64-appstream-htb-rpms&upstream=perl%405.26.3",
5177+
"purl": "pkg:rpm/rhel/perl-IO@1.38-416.el8?distro=rhel-8.2&epoch=0&repositories=rhel-8-for-x86_64-baseos-rpms%2Crhel-8-for-x86_64-appstream-rpms%2Crhel-8-for-x86_64-baseos-beta-rpms%2Crhel-8-for-x86_64-appstream-beta-rpms%2Crhel-8-for-x86_64-baseos-htb-rpms%2Crhel-8-for-x86_64-appstream-htb-rpms&upstream=perl%405.26.3",
51785178
"version": "1.38-416.el8",
51795179
},
51805180
},

0 commit comments

Comments
 (0)