Skip to content

Commit a0e987a

Browse files
committed
Remove strict_required_length option
Remove the strict length check in download.py and check only if an upper bowndary is exceeded. Exact length is not known for some metadata files during download. The check makes the code unnecessarily complicated and is better suited for the later metadata verification step. Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
1 parent 02190cd commit a0e987a

2 files changed

Lines changed: 11 additions & 88 deletions

File tree

tuf/ngclient/_internal/download.py

Lines changed: 10 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,19 @@
3535
logger = logging.getLogger(__name__)
3636

3737

38-
def download_file(url, required_length, fetcher, strict_required_length=True):
38+
def download_file(url, required_length, fetcher):
3939
"""
4040
<Purpose>
4141
Given the url and length of the desired file, this function opens a
42-
connection to 'url' and downloads the file while ensuring its length
43-
matches 'required_length' if 'STRICT_REQUIRED_LENGTH' is True.
42+
connection to 'url' and downloads the file up to 'required_length'.
4443
4544
<Arguments>
4645
url:
4746
A URL string that represents the location of the file.
4847
4948
required_length:
50-
An integer value representing the length of the file.
51-
52-
strict_required_length:
53-
A Boolean indicator used to signal whether we should perform strict
54-
checking of required_length. True by default. We explicitly set this to
55-
False when we know that we want to turn this off for downloading the
56-
timestamp metadata, which has no signed required_length.
49+
An integer value representing the length of the file or an
50+
upper boundary.
5751
5852
<Side Effects>
5953
A file object is created on disk to store the contents of 'url'.
@@ -96,12 +90,10 @@ def download_file(url, required_length, fetcher, strict_required_length=True):
9690
temp_file.write(chunk)
9791
number_of_bytes_received += len(chunk)
9892

99-
# Does the total number of downloaded bytes match the required length?
100-
_check_downloaded_length(
101-
number_of_bytes_received,
102-
required_length,
103-
strict_required_length=strict_required_length,
104-
)
93+
if number_of_bytes_received > required_length:
94+
raise exceptions.DownloadLengthMismatchError(
95+
required_length, number_of_bytes_received
96+
)
10597

10698
except Exception:
10799
# Close 'temp_file'. Any written data is lost.
@@ -114,74 +106,10 @@ def download_file(url, required_length, fetcher, strict_required_length=True):
114106
return temp_file
115107

116108

117-
def download_bytes(url, required_length, fetcher, strict_required_length=True):
109+
def download_bytes(url, required_length, fetcher):
118110
"""Download bytes from given url
119111
120112
Returns the downloaded bytes, otherwise like download_file()
121113
"""
122-
with download_file(
123-
url, required_length, fetcher, strict_required_length
124-
) as dl_file:
114+
with download_file(url, required_length, fetcher) as dl_file:
125115
return dl_file.read()
126-
127-
128-
def _check_downloaded_length(
129-
total_downloaded, required_length, strict_required_length=True
130-
):
131-
"""
132-
<Purpose>
133-
A helper function which checks whether the total number of downloaded
134-
bytes matches our expectation.
135-
136-
<Arguments>
137-
total_downloaded:
138-
The total number of bytes supposedly downloaded for the file in
139-
question.
140-
141-
required_length:
142-
The total number of bytes expected of the file as seen from its metadata
143-
The Timestamp role is always downloaded without a known file length, and
144-
the Root role when the client cannot download any of the required
145-
top-level roles. In both cases, 'required_length' is actually an upper
146-
limit on the length of the downloaded file.
147-
148-
strict_required_length:
149-
A Boolean indicator used to signal whether we should perform strict
150-
checking of required_length. True by default. We explicitly set this to
151-
False when we know that we want to turn this off for downloading the
152-
timestamp metadata, which has no signed required_length.
153-
154-
<Side Effects>
155-
None.
156-
157-
<Exceptions>
158-
securesystemslib.exceptions.DownloadLengthMismatchError, if
159-
strict_required_length is True and total_downloaded is not equal
160-
required_length.
161-
162-
<Returns>
163-
None.
164-
"""
165-
166-
if total_downloaded == required_length:
167-
logger.info("Downloaded %d bytes as expected.", total_downloaded)
168-
169-
else:
170-
# What we downloaded is not equal to the required length, but did we ask
171-
# for strict checking of required length?
172-
if strict_required_length:
173-
logger.info(
174-
"Downloaded %d bytes, but expected %d bytes",
175-
total_downloaded,
176-
required_length,
177-
)
178-
179-
raise exceptions.DownloadLengthMismatchError(
180-
required_length, total_downloaded
181-
)
182-
183-
logger.info(
184-
"Downloaded %d bytes out of upper limit of %d bytes.",
185-
total_downloaded,
186-
required_length,
187-
)

tuf/ngclient/updater.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,7 @@ def _download_metadata(
220220
else:
221221
filename = f"{version}.{rolename}.json"
222222
url = parse.urljoin(self._metadata_base_url, filename)
223-
return download.download_bytes(
224-
url,
225-
length,
226-
self._fetcher,
227-
strict_required_length=False,
228-
)
223+
return download.download_bytes(url, length, self._fetcher)
229224

230225
def _load_local_metadata(self, rolename: str) -> bytes:
231226
with open(os.path.join(self._dir, f"{rolename}.json"), "rb") as f:

0 commit comments

Comments
 (0)