Skip to content

Commit 6de1a38

Browse files
committed
install: validate checksums
Signed-off-by: Filipe Laíns <[email protected]>
1 parent aa06206 commit 6de1a38

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ optional arguments:
2222
```
2323
2424
Missing components:
25-
- Checksum verification
2625
- Custom data installation:
2726
- `headers`
2827
- `data`
2928
3029
### Bootstraping
3130
3231
`install` has a dependency on `installer`, which is used for entrypoint script
33-
generation. As we don't install entrypoint scripts, this dependency is not needed
34-
to install a `install` wheel, making `install` bootstrapable without any
35-
dependencies.
32+
generation and checksum validation. As we don't install entrypoint scripts,
33+
this dependency is not needed to install a `install` wheel, making `install`
34+
bootstrapable without any dependencies. The only thing is that you won't get the
35+
checksum validation, but if you are building from source that shouldn't be a
36+
problem.

install/__init__.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ def _copy_dir(src, dst, ignore=[]): # type: (str, str, List[str]) -> None
8787
shutil.copy2(path, root)
8888

8989

90+
def _validate_checksums(dist_info, dir): # type: (str, str) -> None
91+
try:
92+
import installer.records
93+
94+
with open(os.path.join(dist_info, 'RECORD'), 'r') as f:
95+
lines = [line.strip() for line in f]
96+
97+
for record in installer.records.parse_record_file(lines):
98+
with open(os.path.join(dir, record.path.as_posix()), 'rb') as fr:
99+
if not record.validate(fr.read()):
100+
raise InstallException('Invalid checksum: {}'.format(record))
101+
except ImportError:
102+
import warnings
103+
warnings.warn("'installer' package missing, skipping checksum verification", RuntimeWarning)
104+
105+
90106
def _generate_entrypoint_scripts(file, dir): # type: (str, str) -> None
91107
entrypoints = configparser.ConfigParser()
92108
entrypoints.read(file)
@@ -137,6 +153,8 @@ def build(wheel, cache_dir, optimize=[0, 1, 2]): # type: (str, str, List[int])
137153
elif optimize:
138154
compileall.compile_dir(pkg_cache_dir)
139155

156+
_validate_checksums(dist_info, pkg_cache_dir)
157+
140158
if os.path.isfile(entrypoints_file):
141159
_generate_entrypoint_scripts(entrypoints_file, scripts_cache_dir)
142160

@@ -145,8 +163,6 @@ def build(wheel, cache_dir, optimize=[0, 1, 2]): # type: (str, str, List[int])
145163
with open(os.path.join(cache_dir, 'metadata.pickle'), 'wb') as f:
146164
pickle.dump(metadata, f)
147165

148-
# TODO: verify checksums
149-
150166
# TODO: replace scripts shebang
151167
# TODO: validate platform/python tags to make sure it is compatible
152168
warnings.warn('Platform/Python tags were not verified for compatibity, make sure the wheel is compatible', InstallWarning)

0 commit comments

Comments
 (0)