Skip to content

Commit c22936a

Browse files
authored
feat: extractor support for .pkg and .zst packages (#1580)
1 parent 7f327c9 commit c22936a

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

cve_bin_tool/extractor.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import re
1010
import shutil
1111
import sys
12+
import tarfile
1213
import tempfile
1314

15+
import zstandard
1416
from rpmfile.cli import main as rpmextract
1517

1618
from cve_bin_tool.async_utils import (
@@ -47,6 +49,8 @@ def __init__(self, logger=None, error_mode=ErrorMode.TruncTrace):
4749
self.extract_file_deb: {".deb", ".ipk"},
4850
self.extract_file_cab: {".cab"},
4951
self.extract_file_apk: {".apk"},
52+
self.extract_file_zst: {".zst"},
53+
self.extract_file_pkg: {".pkg"},
5054
self.extract_file_zip: {
5155
".exe",
5256
".zip",
@@ -109,6 +113,40 @@ async def extract_file_rpm(self, filename, extraction_path):
109113
return 1
110114
return 0
111115

116+
async def extract_file_zst(self, filename: str, extraction_path: str) -> int:
117+
"""Extract zstd compressed files"""
118+
119+
dctx = zstandard.ZstdDecompressor()
120+
with ErrorHandler(mode=ErrorMode.Ignore) as e:
121+
with open(filename, "rb") as f:
122+
with dctx.stream_reader(f) as reader:
123+
with tarfile.open(mode="r|", fileobj=reader) as tar:
124+
tar.extractall(extraction_path)
125+
tar.close()
126+
return e.exit_code
127+
128+
async def extract_file_pkg(self, filename: str, extraction_path: str) -> int:
129+
"""Extract pkg files"""
130+
131+
# Tarfile wasn't used here because it can't open [.pkg] files directy
132+
# and failed to manage distinct compression types in differnet versions of FreeBSD packages.
133+
# Reference: https://github.com/intel/cve-bin-tool/pull/1580#discussion_r829346602
134+
if await aio_inpath("tar"):
135+
stdout, stderr, return_code = await aio_run_command(
136+
["tar", "xf", filename, "-C", extraction_path]
137+
)
138+
if (stderr or not stdout) and return_code != 0:
139+
return 1
140+
return 0
141+
if await aio_inpath("7z"):
142+
stdout, stderr, _ = await aio_run_command(
143+
["7z", "x", filename, "-o", extraction_path]
144+
)
145+
if stderr or not stdout:
146+
return 1
147+
return 0
148+
return 1
149+
112150
async def extract_file_deb(self, filename, extraction_path):
113151
"""Extract debian packages"""
114152
if not await aio_inpath("ar"):

0 commit comments

Comments
 (0)