Skip to content

Commit 6359857

Browse files
ziadhanyharsh098
andcommitted
Add support for glib importer
Co-authored-by: Harsh Mishra <hmisraji07@gmail.com> Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent 0318583 commit 6359857

File tree

8 files changed

+442
-0
lines changed

8 files changed

+442
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
12+
import dateparser
13+
from fetchcode.vcs import fetch_via_vcs
14+
from packageurl import PackageURL
15+
from univers.version_range import GenericVersionRange
16+
from univers.versions import InvalidVersion
17+
18+
from vulnerabilities.importer import AdvisoryData
19+
from vulnerabilities.importer import AffectedPackageV2
20+
from vulnerabilities.importer import PackageCommitPatchData
21+
from vulnerabilities.importer import logger
22+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
23+
from vulnerabilities.utils import build_description
24+
25+
26+
class GlibcImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
27+
"""
28+
Pipeline to collect glibc advisories:
29+
"""
30+
31+
pipeline_id = "glibc_importer_v2"
32+
spdx_license_expression = "LGPL-2.1-only"
33+
license_url = "https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=LICENSES"
34+
repo_url = "git+https://sourceware.org/git/glibc.git"
35+
36+
@classmethod
37+
def steps(cls):
38+
return (
39+
cls.clone,
40+
cls.collect_and_store_advisories,
41+
cls.clean_downloads,
42+
)
43+
44+
def clone(self):
45+
self.log(f"Cloning `{self.repo_url}`")
46+
self.vcs_response = fetch_via_vcs(self.repo_url)
47+
48+
def advisories_count(self):
49+
root = Path(self.vcs_response.dest_dir) / "advisories"
50+
return sum(1 for _ in root.rglob("*"))
51+
52+
def collect_advisories(self):
53+
base_path = Path(self.vcs_response.dest_dir) / "advisories"
54+
for file_path in base_path.rglob("*"):
55+
if not file_path.name.startswith("GLIBC-SA"):
56+
continue
57+
58+
with open(file_path) as f:
59+
vulnerability_data = f.read()
60+
61+
parsed_items = self.parse_advisory_text(vulnerability_data)
62+
fixed_commits, fixed_versions, affected_commits, affected_versions = [], [], [], []
63+
advisory_id = file_path.name
64+
cve_id = None
65+
summary = None
66+
description = None
67+
date_published = None
68+
for item in parsed_items:
69+
name = item.get("name")
70+
if name == "summary":
71+
summary = item.get("value")
72+
elif name == "description":
73+
description = item.get("value")
74+
elif name == "CVE-Id":
75+
cve_id = item.get("value")
76+
elif name == "Public-Date":
77+
date_published_value = item.get("value")
78+
date_published = dateparser.parse(date_published_value)
79+
elif name == "Vulnerable-Commit":
80+
fix_commit = item.get("commit")
81+
affected_commits.append(fix_commit)
82+
83+
fixed_version = item.get("version")
84+
affected_versions.append(fixed_version)
85+
elif name == "Fix-Commit":
86+
fix_commit = item.get("commit")
87+
fixed_commits.append(fix_commit)
88+
89+
fixed_version = item.get("version")
90+
fixed_versions.append(fixed_version)
91+
92+
affected_packages = []
93+
purl = PackageURL(
94+
type="generic",
95+
namespace="gnu",
96+
name="gcc",
97+
)
98+
99+
affected_version_range = None
100+
try:
101+
affected_version_range = GenericVersionRange.from_versions(affected_versions)
102+
except InvalidVersion as e:
103+
logger.error(
104+
f"InvalidVersion while parsing affected_version_range: {affected_versions} error: {e}"
105+
)
106+
107+
fixed_version_range = None
108+
try:
109+
fixed_version_range = GenericVersionRange.from_versions(fixed_versions)
110+
except InvalidVersion as e:
111+
logger.error(
112+
f"InvalidVersion while parsing fixed_version_range: {fixed_versions} error: {e}"
113+
)
114+
115+
fixed_by_commit_patches = [
116+
PackageCommitPatchData(
117+
vcs_url="https://sourceware.org/git/glibc.git", commit_hash=fixed_commit
118+
)
119+
for fixed_commit in fixed_commits
120+
]
121+
introduced_by_commit_patches = [
122+
PackageCommitPatchData(
123+
vcs_url="https://sourceware.org/git/glibc.git", commit_hash=affected_commit
124+
)
125+
for affected_commit in affected_commits
126+
]
127+
128+
if (
129+
affected_version_range
130+
or fixed_version_range
131+
or introduced_by_commit_patches
132+
or fixed_by_commit_patches
133+
):
134+
affected_packages.append(
135+
AffectedPackageV2(
136+
package=purl,
137+
affected_version_range=affected_version_range,
138+
fixed_version_range=fixed_version_range,
139+
introduced_by_commit_patches=introduced_by_commit_patches,
140+
fixed_by_commit_patches=fixed_by_commit_patches,
141+
)
142+
)
143+
144+
yield AdvisoryData(
145+
advisory_id=advisory_id,
146+
aliases=[cve_id] if cve_id else [],
147+
summary=build_description(summary, description),
148+
affected_packages=affected_packages,
149+
date_published=date_published,
150+
)
151+
152+
def parse_advisory_text(self, text):
153+
summary, _, tail = text.partition("\n\n")
154+
description, _, metadata = tail.partition("\n\n")
155+
156+
parsed = [
157+
{"name": "summary", "value": summary},
158+
{"name": "description", "value": description},
159+
]
160+
161+
for line in metadata.splitlines():
162+
name, _, value = line.partition(": ")
163+
if name.endswith(
164+
(
165+
"Commit",
166+
"Backport",
167+
)
168+
):
169+
commit, _, version = value.partition(" ")
170+
parsed.append({"name": name, "commit": commit, "version": version.strip(")(")})
171+
else:
172+
parsed.append({"name": name, "value": value})
173+
return parsed
174+
175+
def clean_downloads(self):
176+
"""Cleanup any temporary repository data."""
177+
if self.vcs_response:
178+
self.log(f"Removing cloned repository")
179+
self.vcs_response.delete()
180+
181+
def on_failure(self):
182+
"""Ensure cleanup is always performed on failure."""
183+
self.clean_downloads()
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
from unittest.mock import Mock
12+
from unittest.mock import patch
13+
14+
import pytest
15+
16+
from vulnerabilities.pipelines.v2_importers.glibc_importer import GlibcImporterPipeline
17+
from vulnerabilities.tests import util_tests
18+
19+
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "glibc"
20+
21+
TEST_CVE_FILES = [
22+
TEST_DATA / "advisories" / "GLIBC-SA-2023-0001",
23+
TEST_DATA / "advisories" / "GLIBC-SA-2025-0004",
24+
TEST_DATA / "advisories" / "GLIBC-SA-2026-0002",
25+
]
26+
27+
28+
@pytest.mark.django_db
29+
@pytest.mark.parametrize("glibc_file", TEST_CVE_FILES)
30+
def test_glibc_advisories_per_file(glibc_file):
31+
pipeline = GlibcImporterPipeline()
32+
pipeline.vcs_response = Mock(dest_dir=TEST_DATA)
33+
34+
with patch.object(Path, "rglob", return_value=[glibc_file]):
35+
result = [adv.to_dict() for adv in pipeline.collect_advisories()]
36+
37+
expected_file = glibc_file.with_name(glibc_file.stem + "-expected.json")
38+
util_tests.check_results_against_json(result, expected_file)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
printf: incorrect output for integers with thousands separator and width field
2+
3+
When the printf family of functions is called with a format specifier
4+
that uses an <apostrophe> (enable grouping) and a minimum width
5+
specifier, the resulting output could be larger than reasonably expected
6+
by a caller that computed a tight bound on the buffer size. The
7+
resulting larger than expected output could result in a buffer overflow
8+
in the printf family of functions.
9+
10+
CVE-Id: CVE-2023-25139
11+
Public-Date: 2023-02-02
12+
Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37)
13+
Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38)
14+
Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[
2+
{
3+
"advisory_id": "GLIBC-SA-2023-0001",
4+
"aliases": [
5+
"CVE-2023-25139"
6+
],
7+
"summary": "printf: incorrect output for integers with thousands separator and width field\nWhen the printf family of functions is called with a format specifier\nthat uses an <apostrophe> (enable grouping) and a minimum width\nspecifier, the resulting output could be larger than reasonably expected\nby a caller that computed a tight bound on the buffer size. The\nresulting larger than expected output could result in a buffer overflow\nin the printf family of functions.",
8+
"affected_packages": [
9+
{
10+
"package": {
11+
"type": "generic",
12+
"namespace": "gnu",
13+
"name": "gcc",
14+
"version": "",
15+
"qualifiers": "",
16+
"subpath": ""
17+
},
18+
"affected_version_range": "vers:generic/2.37.0",
19+
"fixed_version_range": "vers:generic/2.37.0-4|2.38.0",
20+
"introduced_by_commit_patches": [
21+
{
22+
"vcs_url": "https://sourceware.org/git/glibc.git",
23+
"commit_hash": "e88b9f0e5cc50cab57a299dc7efe1a4eb385161d",
24+
"patch_text": null,
25+
"patch_checksum": null
26+
}
27+
],
28+
"fixed_by_commit_patches": [
29+
{
30+
"vcs_url": "https://sourceware.org/git/glibc.git",
31+
"commit_hash": "c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0",
32+
"patch_text": null,
33+
"patch_checksum": null
34+
},
35+
{
36+
"vcs_url": "https://sourceware.org/git/glibc.git",
37+
"commit_hash": "07b9521fc6369d000216b96562ff7c0ed32a16c4",
38+
"patch_text": null,
39+
"patch_checksum": null
40+
}
41+
]
42+
}
43+
],
44+
"references_v2": [],
45+
"patches": [],
46+
"severities": [],
47+
"date_published": "2023-02-02T00:00:00",
48+
"weaknesses": [],
49+
"url": ""
50+
}
51+
]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
power10: strncmp fails to save and restore nonvolatile vector registers
2+
3+
The Power 10 implementation of strncmp in
4+
sysdeps/powerpc/powerpc64/le/power10/strncmp.S failed to save/restore
5+
nonvolatile vector registers in the 32-byte aligned loop path. This
6+
results in callers reading content from those registers in a different
7+
context, potentially altering program logic.
8+
9+
There could be a program context where a user controlled string could
10+
leak through strncmp into program code, thus altering its logic. There
11+
is also a potential for sensitive strings passed into strncmp leaking
12+
through the clobbered registers into parts of the calling program that
13+
should otherwise not have had access to those strings.
14+
15+
The impact of this flaw is limited to applications running on Power 10
16+
hardware that use the nonvolatile vector registers, i.e. v20 to v31
17+
assuming that they have been treated in accordance with the OpenPower
18+
psABI. It is possible to work around the issue for those specific
19+
applications by setting the glibc.cpu.hwcaps tunable to "-arch_3_1" like
20+
so:
21+
22+
export GLIBC_TUNABLES=glibc.cpu.hwcaps=-arch_3_1
23+
24+
CVE-Id: CVE-2025-5745
25+
Public-Date: 2025-06-05
26+
Vulnerable-Commit: 23f0d81608d0ca6379894ef81670cf30af7fd081 (2.40)
27+
Fix-Commit: 63c60101ce7c5eac42be90f698ba02099b41b965 (2.42)
28+
Fix-Commit: 84bdbf8a6f2fdafd3661489dbb7f79835a52da82 (2.41-57)
29+
Fix-Commit: 42a5a940c974d02540c8da26d6374c744d148cb9 (2.40-136)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[
2+
{
3+
"advisory_id": "GLIBC-SA-2025-0004",
4+
"aliases": [
5+
"CVE-2025-5745"
6+
],
7+
"summary": "power10: strncmp fails to save and restore nonvolatile vector registers\nThe Power 10 implementation of strncmp in\nsysdeps/powerpc/powerpc64/le/power10/strncmp.S failed to save/restore\nnonvolatile vector registers in the 32-byte aligned loop path. This\nresults in callers reading content from those registers in a different\ncontext, potentially altering program logic.",
8+
"affected_packages": [
9+
{
10+
"package": {
11+
"type": "generic",
12+
"namespace": "gnu",
13+
"name": "gcc",
14+
"version": "",
15+
"qualifiers": "",
16+
"subpath": ""
17+
},
18+
"affected_version_range": "vers:generic/2.40.0",
19+
"fixed_version_range": "vers:generic/2.40.0-136|2.41.0-57|2.42.0",
20+
"introduced_by_commit_patches": [
21+
{
22+
"vcs_url": "https://sourceware.org/git/glibc.git",
23+
"commit_hash": "23f0d81608d0ca6379894ef81670cf30af7fd081",
24+
"patch_text": null,
25+
"patch_checksum": null
26+
}
27+
],
28+
"fixed_by_commit_patches": [
29+
{
30+
"vcs_url": "https://sourceware.org/git/glibc.git",
31+
"commit_hash": "63c60101ce7c5eac42be90f698ba02099b41b965",
32+
"patch_text": null,
33+
"patch_checksum": null
34+
},
35+
{
36+
"vcs_url": "https://sourceware.org/git/glibc.git",
37+
"commit_hash": "84bdbf8a6f2fdafd3661489dbb7f79835a52da82",
38+
"patch_text": null,
39+
"patch_checksum": null
40+
},
41+
{
42+
"vcs_url": "https://sourceware.org/git/glibc.git",
43+
"commit_hash": "42a5a940c974d02540c8da26d6374c744d148cb9",
44+
"patch_text": null,
45+
"patch_checksum": null
46+
}
47+
]
48+
}
49+
],
50+
"references_v2": [],
51+
"patches": [],
52+
"severities": [],
53+
"date_published": "2025-06-05T00:00:00",
54+
"weaknesses": [],
55+
"url": ""
56+
}
57+
]

0 commit comments

Comments
 (0)