Skip to content

Commit ea8b1ff

Browse files
committed
pin the stage0 hashes in src/stage0.json
1 parent 80b81ad commit ea8b1ff

File tree

6 files changed

+419
-37
lines changed

6 files changed

+419
-37
lines changed

Cargo.lock

+2
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ version = "0.1.0"
226226
dependencies = [
227227
"anyhow",
228228
"curl",
229+
"indexmap",
229230
"serde",
230231
"serde_json",
231232
"toml",
@@ -1674,6 +1675,7 @@ checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
16741675
dependencies = [
16751676
"autocfg",
16761677
"hashbrown",
1678+
"serde",
16771679
]
16781680

16791681
[[package]]

src/bootstrap/bootstrap.py

+36-27
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,17 @@ def support_xz():
2525
except tarfile.CompressionError:
2626
return False
2727

28-
def get(url, path, verbose=False, do_verify=True):
29-
suffix = '.sha256'
30-
sha_url = url + suffix
28+
def get(base, url, path, checksums, verbose=False, do_verify=True):
3129
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
3230
temp_path = temp_file.name
33-
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file:
34-
sha_path = sha_file.name
3531

3632
try:
3733
if do_verify:
38-
download(sha_path, sha_url, False, verbose)
34+
if url not in checksums:
35+
raise RuntimeError("src/stage0.json doesn't contain a checksum for {}".format(url))
36+
sha256 = checksums[url]
3937
if os.path.exists(path):
40-
if verify(path, sha_path, False):
38+
if verify(path, sha256, False):
4139
if verbose:
4240
print("using already-download file", path)
4341
return
@@ -46,23 +44,17 @@ def get(url, path, verbose=False, do_verify=True):
4644
print("ignoring already-download file",
4745
path, "due to failed verification")
4846
os.unlink(path)
49-
download(temp_path, url, True, verbose)
50-
if do_verify and not verify(temp_path, sha_path, verbose):
47+
download(temp_path, "{}/{}".format(base, url), True, verbose)
48+
if do_verify and not verify(temp_path, sha256, verbose):
5149
raise RuntimeError("failed verification")
5250
if verbose:
5351
print("moving {} to {}".format(temp_path, path))
5452
shutil.move(temp_path, path)
5553
finally:
56-
delete_if_present(sha_path, verbose)
57-
delete_if_present(temp_path, verbose)
58-
59-
60-
def delete_if_present(path, verbose):
61-
"""Remove the given file if present"""
62-
if os.path.isfile(path):
63-
if verbose:
64-
print("removing", path)
65-
os.unlink(path)
54+
if os.path.isfile(temp_path):
55+
if verbose:
56+
print("removing", temp_path)
57+
os.unlink(temp_path)
6658

6759

6860
def download(path, url, probably_big, verbose):
@@ -99,14 +91,12 @@ def _download(path, url, probably_big, verbose, exception):
9991
exception=exception)
10092

10193

102-
def verify(path, sha_path, verbose):
94+
def verify(path, expected, verbose):
10395
"""Check if the sha256 sum of the given path is valid"""
10496
if verbose:
10597
print("verifying", path)
10698
with open(path, "rb") as source:
10799
found = hashlib.sha256(source.read()).hexdigest()
108-
with open(sha_path, "r") as sha256sum:
109-
expected = sha256sum.readline().split()[0]
110100
verified = found == expected
111101
if not verified:
112102
print("invalid checksum:\n"
@@ -375,6 +365,7 @@ def channel(self):
375365
class RustBuild(object):
376366
"""Provide all the methods required to build Rust"""
377367
def __init__(self):
368+
self.checksums_sha256 = {}
378369
self.stage0_compiler = None
379370
self.stage0_rustfmt = None
380371
self._download_url = ''
@@ -529,12 +520,21 @@ def _download_component_helper(
529520
os.makedirs(rustc_cache)
530521

531522
if stage0:
532-
url = "{}/dist/{}".format(self._download_url, key)
523+
base = self._download_url
524+
url = "dist/{}".format(key)
533525
else:
534-
url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit)
526+
base = "https://ci-artifacts.rust-lang.org"
527+
url = "rustc-builds/{}".format(self.rustc_commit)
535528
tarball = os.path.join(rustc_cache, filename)
536529
if not os.path.exists(tarball):
537-
get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=stage0)
530+
get(
531+
base,
532+
"{}/{}".format(url, filename),
533+
tarball,
534+
self.checksums_sha256,
535+
verbose=self.verbose,
536+
do_verify=stage0,
537+
)
538538
unpack(tarball, tarball_suffix, self.bin_root(stage0), match=pattern, verbose=self.verbose)
539539

540540
def _download_ci_llvm(self, llvm_sha, llvm_assertions):
@@ -544,7 +544,8 @@ def _download_ci_llvm(self, llvm_sha, llvm_assertions):
544544
if not os.path.exists(rustc_cache):
545545
os.makedirs(rustc_cache)
546546

547-
url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
547+
base = "https://ci-artifacts.rust-lang.org"
548+
url = "rustc-builds/{}".format(llvm_sha)
548549
if llvm_assertions:
549550
url = url.replace('rustc-builds', 'rustc-builds-alt')
550551
# ci-artifacts are only stored as .xz, not .gz
@@ -556,7 +557,14 @@ def _download_ci_llvm(self, llvm_sha, llvm_assertions):
556557
filename = "rust-dev-nightly-" + self.build + tarball_suffix
557558
tarball = os.path.join(rustc_cache, filename)
558559
if not os.path.exists(tarball):
559-
get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=False)
560+
get(
561+
base,
562+
"{}/{}".format(url, filename),
563+
tarball,
564+
self.checksums_sha256,
565+
verbose=self.verbose,
566+
do_verify=False,
567+
)
560568
unpack(tarball, tarball_suffix, self.llvm_root(),
561569
match="rust-dev",
562570
verbose=self.verbose)
@@ -1158,6 +1166,7 @@ def bootstrap(help_triggered):
11581166

11591167
with open(os.path.join(build.rust_root, "src", "stage0.json")) as f:
11601168
data = json.load(f)
1169+
build.checksums_sha256 = data["checksums_sha256"]
11611170
build.stage0_compiler = Stage0Toolchain(data["compiler"])
11621171
if data.get("rustfmt") is not None:
11631172
build.stage0_rustfmt = Stage0Toolchain(data["rustfmt"])

src/bootstrap/bootstrap_test.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ class VerifyTestCase(unittest.TestCase):
1818
def setUp(self):
1919
self.container = tempfile.mkdtemp()
2020
self.src = os.path.join(self.container, "src.txt")
21-
self.sums = os.path.join(self.container, "sums")
2221
self.bad_src = os.path.join(self.container, "bad.txt")
2322
content = "Hello world"
2423

24+
self.expected = hashlib.sha256(content.encode("utf-8")).hexdigest()
25+
2526
with open(self.src, "w") as src:
2627
src.write(content)
27-
with open(self.sums, "w") as sums:
28-
sums.write(hashlib.sha256(content.encode("utf-8")).hexdigest())
2928
with open(self.bad_src, "w") as bad:
3029
bad.write("Hello!")
3130

@@ -34,11 +33,11 @@ def tearDown(self):
3433

3534
def test_valid_file(self):
3635
"""Check if the sha256 sum of the given file is valid"""
37-
self.assertTrue(bootstrap.verify(self.src, self.sums, False))
36+
self.assertTrue(bootstrap.verify(self.src, self.expected, False))
3837

3938
def test_invalid_file(self):
4039
"""Should verify that the file is invalid"""
41-
self.assertFalse(bootstrap.verify(self.bad_src, self.sums, False))
40+
self.assertFalse(bootstrap.verify(self.bad_src, self.expected, False))
4241

4342

4443
class ProgramOutOfDate(unittest.TestCase):

0 commit comments

Comments
 (0)