Skip to content

Commit 388c535

Browse files
e3krisztianqkaiser
authored andcommitted
refactor: shuffle code to their proper place
1 parent 3acae4f commit 388c535

File tree

4 files changed

+42
-37
lines changed

4 files changed

+42
-37
lines changed

tests/handlers/filesystem/test_romfs.py

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
from pathlib import Path
2-
31
import pytest
42

53
from unblob.file_utils import File
6-
from unblob.handlers.filesystem.romfs import get_string, is_safe_path, valid_checksum
4+
from unblob.handlers.filesystem.romfs import get_string, valid_checksum
75

86

97
@pytest.mark.parametrize(
@@ -44,23 +42,3 @@ def test_get_string(content, expected):
4442
)
4543
def test_valid_checksum(content, valid):
4644
assert valid_checksum(content) == valid
47-
48-
49-
@pytest.mark.parametrize(
50-
"basedir, path, expected",
51-
[
52-
("/lib/out", "/lib/out/file", True),
53-
("/lib/out", "file", True),
54-
("/lib/out", "dir/file", True),
55-
("/lib/out", "some/dir/file", True),
56-
("/lib/out", "some/dir/../file", True),
57-
("/lib/out", "some/dir/../../file", True),
58-
("/lib/out", "some/dir/../../../file", False),
59-
("/lib/out", "some/dir/../../../", False),
60-
("/lib/out", "some/dir/../../..", False),
61-
("/lib/out", "../file", False),
62-
("/lib/out", "/lib/out/../file", False),
63-
],
64-
)
65-
def test_is_safe_path(basedir, path, expected):
66-
assert is_safe_path(Path(basedir), Path(path)) is expected

tests/test_file_utils.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import io
2+
from pathlib import Path
23
from typing import List
34

45
import pytest
@@ -14,13 +15,34 @@
1415
convert_int64,
1516
decode_multibyte_integer,
1617
get_endian,
18+
is_safe_path,
1719
iterate_file,
1820
iterate_patterns,
1921
round_down,
2022
round_up,
2123
)
2224

2325

26+
@pytest.mark.parametrize(
27+
"basedir, path, expected",
28+
[
29+
("/lib/out", "/lib/out/file", True),
30+
("/lib/out", "file", True),
31+
("/lib/out", "dir/file", True),
32+
("/lib/out", "some/dir/file", True),
33+
("/lib/out", "some/dir/../file", True),
34+
("/lib/out", "some/dir/../../file", True),
35+
("/lib/out", "some/dir/../../../file", False),
36+
("/lib/out", "some/dir/../../../", False),
37+
("/lib/out", "some/dir/../../..", False),
38+
("/lib/out", "../file", False),
39+
("/lib/out", "/lib/out/../file", False),
40+
],
41+
)
42+
def test_is_safe_path(basedir, path, expected):
43+
assert is_safe_path(Path(basedir), Path(path)) is expected
44+
45+
2446
@pytest.mark.parametrize(
2547
"size, alignment, result",
2648
[

unblob/extractor.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from structlog import get_logger
77

8-
from .file_utils import iterate_file
8+
from .file_utils import carve, is_safe_path
99
from .models import Chunk, File, TaskResult, UnknownChunk, ValidChunk
1010
from .report import MaliciousSymlinkRemoved
1111

@@ -14,12 +14,8 @@
1414

1515
def carve_chunk_to_file(carve_path: Path, file: File, chunk: Chunk):
1616
"""Extract valid chunk to a file, which we then pass to another tool to extract it."""
17-
carve_path.parent.mkdir(parents=True, exist_ok=True)
1817
logger.debug("Carving chunk", path=carve_path)
19-
20-
with carve_path.open("xb") as f:
21-
for data in iterate_file(file, chunk.start_offset, chunk.size):
22-
f.write(data)
18+
carve(carve_path, file, chunk.start_offset, chunk.size)
2319

2420

2521
def fix_permission(path: Path):
@@ -32,14 +28,6 @@ def fix_permission(path: Path):
3228
path.chmod(0o775)
3329

3430

35-
def is_safe_path(basedir: Path, path: Path) -> bool:
36-
try:
37-
basedir.joinpath(path).resolve().relative_to(basedir.resolve())
38-
except ValueError:
39-
return False
40-
return True
41-
42-
4331
def is_recursive_link(path: Path) -> bool:
4432
try:
4533
path.resolve()

unblob/file_utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
DEFAULT_BUFSIZE = shutil.COPY_BUFSIZE # type: ignore
1616

1717

18+
def is_safe_path(basedir: Path, path: Path) -> bool:
19+
try:
20+
basedir.joinpath(path).resolve().relative_to(basedir.resolve())
21+
except ValueError:
22+
return False
23+
return True
24+
25+
1826
class SeekError(ValueError):
1927
"""Specific ValueError for File.seek."""
2028

@@ -252,6 +260,15 @@ def iterate_file(
252260
yield data
253261

254262

263+
def carve(carve_path: Path, file: File, start_offset: int, size: int):
264+
"""Extract part of a file."""
265+
carve_path.parent.mkdir(parents=True, exist_ok=True)
266+
267+
with carve_path.open("xb") as f:
268+
for data in iterate_file(file, start_offset, size):
269+
f.write(data)
270+
271+
255272
def stream_scan(scanner, file: File):
256273
"""Scan the whole file by increment of DEFAULT_BUFSIZE using Hyperscan's streaming mode."""
257274
scanner.scan(file, DEFAULT_BUFSIZE)

0 commit comments

Comments
 (0)