Skip to content

Commit 687d7bb

Browse files
chore: address various coverity issues (#301)
**Description:** This PR addresses various coverity findings. **Changes Made:** * don't send `x-powered-by` header on media server * re-enable certificate verification in downloader * switch from md5 to sha256 for file caching **Testing Done:** Tested locally on B580 **Checklist:** - [x] I have tested the changes locally. - [x] I have self-reviewed the code changes.
1 parent 17e6abc commit 687d7bb

File tree

5 files changed

+138
-148
lines changed

5 files changed

+138
-148
lines changed

WebUI/electron/subprocesses/mediaServer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const port: number = Number(process.env.PORT_NUMBER)
66
const mediaPath: string = process.env.MEDIA_DIRECTORY!
77

88
app.use(express.static(mediaPath))
9+
app.disable('x-powered-by')
910

1011
app.listen(port, () => {
1112
console.log(`Media server started on port ${port}`, 'electron-backend')

backend-shared/utils.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,35 +135,28 @@ def check_defaultbackend_mmodel_exist(type: int, repo_id: str) -> bool:
135135
)
136136

137137
# File operations
138-
def calculate_md5(file_path: str):
139-
"""Calculate the MD5 hash of a file"""
138+
def calculate_sha256(file_path: str):
139+
"""Calculate the SHA256 hash of a file"""
140140
with open(file_path, "rb") as f:
141141
file_hash = hashlib.md5()
142142
while chunk := f.read(8192):
143143
file_hash.update(chunk)
144144
return file_hash.hexdigest()
145145

146-
def calculate_md5_from_stream(file_stream: IO[bytes]):
147-
"""Calculate the MD5 hash of a file stream"""
148-
file_hash = hashlib.md5()
149-
for chunk in iter(lambda: file_stream.read(8192), b""):
150-
file_hash.update(chunk)
151-
return file_hash.hexdigest()
152-
153-
def create_cache_path(md5: str, file_size: int):
154-
"""Create a cache path for a file based on its MD5 hash and size"""
146+
def create_cache_path(sha256: str, file_size: int):
147+
"""Create a cache path for a file based on its SHA256 hash and size"""
155148
cache_dir = "./cache"
156-
sub_dirs = [md5[i : i + 4] for i in range(0, len(md5), 4)]
149+
sub_dirs = [sha256[i : i + 4] for i in range(0, len(sha256), 4)]
157150
cache_path = os.path.abspath(
158-
os.path.join(cache_dir, *sub_dirs, f"{md5}_{file_size}")
151+
os.path.join(cache_dir, *sub_dirs, f"{sha256}_{file_size}")
159152
)
160153
return cache_path
161154

162155
def cache_file(file_path: IO[bytes] | str, file_size: int):
163-
"""Cache a file using its MD5 hash and size"""
164-
md5 = calculate_md5(file_path)
156+
"""Cache a file using its SHA256 hash and size"""
157+
sha256 = calculate_sha256(file_path)
165158

166-
cache_path = create_cache_path(md5, file_size)
159+
cache_path = create_cache_path(sha256, file_size)
167160

168161
if not os.path.exists(cache_path):
169162
os.makedirs(os.path.dirname(cache_path), exist_ok=True)

service/aipg_utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
repo_local_root_dir_name = utils.repo_local_root_dir_name
2525
flat_repo_local_dir_name = utils.flat_repo_local_dir_name
2626
get_model_path = utils.get_model_path
27-
calculate_md5 = utils.calculate_md5
2827
create_cache_path = utils.create_cache_path
29-
calculate_md5_from_stream = utils.calculate_md5_from_stream
3028
cache_file = utils.cache_file
3129
is_single_file = utils.is_single_file
3230
remove_existing_filesystem_resource = utils.remove_existing_filesystem_resource

service/file_downloader.py

Lines changed: 126 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,126 @@
1-
from io import BufferedWriter
2-
import os
3-
import time
4-
import traceback
5-
from typing import Callable
6-
import requests
7-
from threading import Thread
8-
from exceptions import DownloadException
9-
10-
11-
class FileDownloader:
12-
on_download_progress: Callable[[str, int, int, int], None] = None
13-
on_download_completed: Callable[[str, Exception], None] = None
14-
url: str
15-
filename: str
16-
basename: str
17-
total_size: int
18-
download_size: int
19-
download_stop: bool
20-
prev_sec_download_size: int
21-
22-
def __init__(self):
23-
self.download_stop = False
24-
self.download_size = 0
25-
self.completed = False
26-
self.total_size = 0
27-
self.prev_sec_download_size = 0
28-
self.report_thread = None
29-
30-
def download_file(self, url: str, file_path: str):
31-
self.url = url
32-
self.basename = os.path.basename(file_path)
33-
self.download_stop = False
34-
self.filename = file_path
35-
self.prev_sec_download_size = 0
36-
self.download_size = 0
37-
self.completed = False
38-
self.report_thread = None
39-
error = None
40-
report_thread = None
41-
try:
42-
response, fw = self.__init_download(self.url, self.filename)
43-
self.total_size = int(response.headers.get("Content-Length"))
44-
if self.on_download_progress is not None:
45-
report_thread = self.__start_report_download_progress()
46-
self.__start_download(response, fw)
47-
except Exception as e:
48-
error = e
49-
finally:
50-
self.completed = True
51-
if report_thread is not None:
52-
report_thread.join()
53-
54-
if self.on_download_completed is not None:
55-
self.on_download_completed(self.basename, error)
56-
57-
def __init_download(
58-
self, url: str, file_path: str
59-
) -> tuple[requests.Response, BufferedWriter]:
60-
if os.path.exists(file_path):
61-
start_pos = os.path.getsize(file_path)
62-
else:
63-
os.makedirs(os.path.dirname(file_path), exist_ok=True)
64-
start_pos = 0
65-
66-
if start_pos > 0:
67-
# download skip exists part
68-
response = requests.get(
69-
url,
70-
stream=True,
71-
verify=False,
72-
headers={"Range": f"bytes={start_pos}-"},
73-
)
74-
fw = open(file_path, "ab")
75-
else:
76-
response = requests.get(url, stream=True, verify=False)
77-
fw = open(file_path, "wb")
78-
79-
return response, fw
80-
81-
def __start_download(self, response: requests.Response, fw: BufferedWriter):
82-
retry = 0
83-
while True:
84-
try:
85-
with response:
86-
with fw:
87-
for bytes in response.iter_content(chunk_size=4096):
88-
self.download_size += bytes.__len__()
89-
fw.write(bytes)
90-
91-
if self.download_stop:
92-
print(
93-
f"FileDownloader thread {Thread.native_id} exit by stop"
94-
)
95-
break
96-
break
97-
except Exception:
98-
traceback.print_exc()
99-
retry += 1
100-
if retry > 3:
101-
raise DownloadException(self.url)
102-
else:
103-
print(
104-
f"FileDownloader thread {Thread.native_id} retry {retry} times"
105-
)
106-
time.sleep(1)
107-
response, fw = self.__init_download(self.url, self.filename)
108-
109-
def __start_report_download_progress(self):
110-
report_thread = Thread(target=self.__report_download_progress)
111-
report_thread.start()
112-
return report_thread
113-
114-
def __report_download_progress(self):
115-
while not self.download_stop and not self.completed:
116-
self.on_download_progress(
117-
self.basename,
118-
self.download_size,
119-
self.total_size,
120-
self.download_size - self.prev_sec_download_size,
121-
)
122-
123-
self.prev_sec_download_size = self.download_size
124-
time.sleep(1)
125-
126-
def stop_download(self):
127-
self.download_stop = True
1+
from io import BufferedWriter
2+
import os
3+
import time
4+
import traceback
5+
from typing import Callable
6+
import requests
7+
from threading import Thread
8+
from exceptions import DownloadException
9+
10+
11+
class FileDownloader:
12+
on_download_progress: Callable[[str, int, int, int], None] = None
13+
on_download_completed: Callable[[str, Exception], None] = None
14+
url: str
15+
filename: str
16+
basename: str
17+
total_size: int
18+
download_size: int
19+
download_stop: bool
20+
prev_sec_download_size: int
21+
22+
def __init__(self):
23+
self.download_stop = False
24+
self.download_size = 0
25+
self.completed = False
26+
self.total_size = 0
27+
self.prev_sec_download_size = 0
28+
self.report_thread = None
29+
30+
def download_file(self, url: str, file_path: str):
31+
self.url = url
32+
self.basename = os.path.basename(file_path)
33+
self.download_stop = False
34+
self.filename = file_path
35+
self.prev_sec_download_size = 0
36+
self.download_size = 0
37+
self.completed = False
38+
self.report_thread = None
39+
error = None
40+
report_thread = None
41+
try:
42+
response, fw = self.__init_download(self.url, self.filename)
43+
self.total_size = int(response.headers.get("Content-Length"))
44+
if self.on_download_progress is not None:
45+
report_thread = self.__start_report_download_progress()
46+
self.__start_download(response, fw)
47+
except Exception as e:
48+
error = e
49+
finally:
50+
self.completed = True
51+
if report_thread is not None:
52+
report_thread.join()
53+
54+
if self.on_download_completed is not None:
55+
self.on_download_completed(self.basename, error)
56+
57+
def __init_download(
58+
self, url: str, file_path: str
59+
) -> tuple[requests.Response, BufferedWriter]:
60+
if os.path.exists(file_path):
61+
start_pos = os.path.getsize(file_path)
62+
else:
63+
os.makedirs(os.path.dirname(file_path), exist_ok=True)
64+
start_pos = 0
65+
66+
if start_pos > 0:
67+
# download skip exists part
68+
response = requests.get(
69+
url,
70+
stream=True,
71+
headers={"Range": f"bytes={start_pos}-"},
72+
)
73+
fw = open(file_path, "ab")
74+
else:
75+
response = requests.get(url, stream=True)
76+
fw = open(file_path, "wb")
77+
78+
return response, fw
79+
80+
def __start_download(self, response: requests.Response, fw: BufferedWriter):
81+
retry = 0
82+
while True:
83+
try:
84+
with response:
85+
with fw:
86+
for bytes in response.iter_content(chunk_size=4096):
87+
self.download_size += bytes.__len__()
88+
fw.write(bytes)
89+
90+
if self.download_stop:
91+
print(
92+
f"FileDownloader thread {Thread.native_id} exit by stop"
93+
)
94+
break
95+
break
96+
except Exception:
97+
traceback.print_exc()
98+
retry += 1
99+
if retry > 3:
100+
raise DownloadException(self.url)
101+
else:
102+
print(
103+
f"FileDownloader thread {Thread.native_id} retry {retry} times"
104+
)
105+
time.sleep(1)
106+
response, fw = self.__init_download(self.url, self.filename)
107+
108+
def __start_report_download_progress(self):
109+
report_thread = Thread(target=self.__report_download_progress)
110+
report_thread.start()
111+
return report_thread
112+
113+
def __report_download_progress(self):
114+
while not self.download_stop and not self.completed:
115+
self.on_download_progress(
116+
self.basename,
117+
self.download_size,
118+
self.total_size,
119+
self.download_size - self.prev_sec_download_size,
120+
)
121+
122+
self.prev_sec_download_size = self.download_size
123+
time.sleep(1)
124+
125+
def stop_download(self):
126+
self.download_stop = True

service/model_downloader.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,12 @@ def init_download(self, file: HFDonloadItem):
330330
response = requests.get(
331331
file.url,
332332
stream=True,
333-
verify=False,
334333
headers=headers,
335334
)
336335
fw = open(file.save_filename, "ab")
337336
else:
338337
response = requests.get(
339-
file.url, stream=True, verify=False, headers=headers
338+
file.url, stream=True, headers=headers
340339
)
341340
fw = open(file.save_filename, "wb")
342341

@@ -361,7 +360,7 @@ def is_access_granted(self, repo_id: str, model_type, backend : str):
361360
self.build_queue(file_list)
362361
file = self.file_queue.get_nowait()
363362

364-
response = requests.head(file.url, verify=False, headers=headers, allow_redirects=True)
363+
response = requests.head(file.url, headers=headers, allow_redirects=True)
365364

366365
return response.status_code == 200
367366

0 commit comments

Comments
 (0)