Skip to content

Commit 394e831

Browse files
author
Ashutosh Gupta
committed
Merge pull request #1 from ashutoshcipher/codex/find-and-fix-bugs-in-code
Fix ignored path handling in hashing configuration Signed-off-by: Ashutosh Gupta <[email protected]>
2 parents ca78773 + 1559fa6 commit 394e831

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

scripts/tests/verify_test.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def test_verify_key_v0_3_1(self, base_path: pathlib.Path):
4141
public_key=public_key
4242
).set_hashing_config(
4343
model_signing.hashing.Config().set_ignored_paths(
44-
paths=list(ignore_paths) + [signature],
44+
paths=list(ignore_paths) + [signature.name],
4545
ignore_git_paths=ignore_git_paths,
4646
)
4747
).verify(model_path, signature)
@@ -61,7 +61,7 @@ def test_verify_certificate_v0_3_1(self, base_path: pathlib.Path):
6161
log_fingerprints=log_fingerprints,
6262
).set_hashing_config(
6363
model_signing.hashing.Config().set_ignored_paths(
64-
paths=list(ignore_paths) + [signature],
64+
paths=list(ignore_paths) + [signature.name],
6565
ignore_git_paths=ignore_git_paths,
6666
)
6767
).verify(model_path, signature)
@@ -83,7 +83,7 @@ def test_verify_sigstore_v0_3_1(self, base_path: pathlib.Path):
8383
use_staging=use_staging,
8484
).set_hashing_config(
8585
model_signing.hashing.Config().set_ignored_paths(
86-
paths=list(ignore_paths) + [signature],
86+
paths=list(ignore_paths) + [signature.name],
8787
ignore_git_paths=ignore_git_paths,
8888
)
8989
).verify(model_path, signature)
@@ -101,7 +101,7 @@ def test_verify_key_v1_0_0(self, base_path: pathlib.Path):
101101
public_key=public_key
102102
).set_hashing_config(
103103
model_signing.hashing.Config().set_ignored_paths(
104-
paths=list(ignore_paths) + [signature],
104+
paths=list(ignore_paths) + [signature.name],
105105
ignore_git_paths=ignore_git_paths,
106106
)
107107
).verify(model_path, signature)
@@ -121,7 +121,7 @@ def test_verify_certificate_v1_0_0(self, base_path: pathlib.Path):
121121
log_fingerprints=log_fingerprints,
122122
).set_hashing_config(
123123
model_signing.hashing.Config().set_ignored_paths(
124-
paths=list(ignore_paths) + [signature],
124+
paths=list(ignore_paths) + [signature.name],
125125
ignore_git_paths=ignore_git_paths,
126126
)
127127
).verify(model_path, signature)
@@ -143,7 +143,7 @@ def test_verify_sigstore_v1_0_0(self, base_path: pathlib.Path):
143143
use_staging=use_staging,
144144
).set_hashing_config(
145145
model_signing.hashing.Config().set_ignored_paths(
146-
paths=list(ignore_paths) + [signature],
146+
paths=list(ignore_paths) + [signature.name],
147147
ignore_git_paths=ignore_git_paths,
148148
)
149149
).verify(model_path, signature)

src/model_signing/hashing.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,23 @@ def hash(
148148
files_to_hash: Optional[Iterable[PathLike]] = None,
149149
) -> manifest.Manifest:
150150
"""Hashes a model using the current configuration."""
151-
# All paths in ignored_paths must have model_path as prefix
151+
# All paths in ``_ignored_paths`` are expected to be relative to the
152+
# model directory. Join them to ``model_path`` and ensure they do not
153+
# escape it.
154+
model_path = pathlib.Path(model_path)
152155
ignored_paths = []
153156
for p in self._ignored_paths:
154-
rp = os.path.relpath(p, model_path)
155-
# rp may start with "../" if it is not relative to model_path
156-
if not rp.startswith("../"):
157-
ignored_paths.append(pathlib.Path(os.path.join(model_path, rp)))
157+
full = model_path / p
158+
try:
159+
full.relative_to(model_path)
160+
except ValueError:
161+
continue
162+
ignored_paths.append(full)
158163

159164
if self._ignore_git_paths:
160165
ignored_paths.extend(
161166
[
162-
os.path.join(model_path, p)
167+
model_path / p
163168
for p in [
164169
".git/",
165170
".gitattributes",
@@ -357,11 +362,9 @@ def set_ignored_paths(
357362
Returns:
358363
The new hashing configuration with a new set of ignored paths.
359364
"""
360-
# Use relpath to possibly fix weird paths like '../a/b' -> 'b'
361-
# when '../a/' is a no-op
362-
self._ignored_paths = frozenset(
363-
{pathlib.Path(p).resolve() for p in paths}
364-
)
365+
# Preserve the user-provided relative paths; they are resolved against
366+
# the model directory later when hashing.
367+
self._ignored_paths = frozenset(pathlib.Path(p) for p in paths)
365368
self._ignore_git_paths = ignore_git_paths
366369
return self
367370

@@ -376,7 +379,15 @@ def add_ignored_paths(
376379
the model directory.
377380
"""
378381
newset = set(self._ignored_paths)
379-
newset.update([os.path.join(model_path, p) for p in paths])
382+
model_path = pathlib.Path(model_path)
383+
for p in paths:
384+
candidate = pathlib.Path(p)
385+
full = model_path / candidate
386+
try:
387+
full.relative_to(model_path)
388+
except ValueError:
389+
continue
390+
newset.add(candidate)
380391
self._ignored_paths = newset
381392

382393
def set_allow_symlinks(self, allow_symlinks: bool) -> Self:

tests/hashing_config_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from model_signing import hashing
2+
3+
4+
def test_set_ignored_paths_relative_to_model(tmp_path, monkeypatch):
5+
model = tmp_path / "model"
6+
model.mkdir()
7+
(model / "ignored.txt").write_text("skip")
8+
(model / "keep.txt").write_text("keep")
9+
10+
cfg = hashing.Config().set_ignored_paths(paths=["ignored.txt"])
11+
# Change working directory to ensure ignored paths aren't resolved against
12+
# the current directory used at hashing time.
13+
monkeypatch.chdir(tmp_path)
14+
15+
manifest = cfg.hash(model)
16+
identifiers = {rd.identifier for rd in manifest.resource_descriptors()}
17+
assert "ignored.txt" not in identifiers
18+
assert "keep.txt" in identifiers

0 commit comments

Comments
 (0)