Handle malformed remote and edge-case data instead of panicking
- distro_info: malformed CSV rows are skipped with a warning, dates that fail to parse become None, and all plain HTTP requests go through a shared reqwest client with connect/total timeouts - package_info: the Sources stanza iterator is iterative (a crafted index with many blank stanzas overflowed the stack), stanzas missing a Version are skipped, and failed series/pocket probes are summarized in the final 'not found' error instead of being silently dropped - pull: no double unwrap on the remote-derived artifact filename, an empty series list is an error, and streaming downloads get a per-request timeout - deb/cross: dpkg-architecture output parsing skips unexpected lines and its exit status is checked, as is dpkg --add-architecture - changelog: version increments parse as u64 with checked arithmetic (1.0-20250123123456 used to panic on the u32 parse)
This commit is contained in:
+25
-7
@@ -310,8 +310,14 @@ async fn download_file_checksum(
|
||||
target_dir: &Path,
|
||||
progress: ProgressCallback<'_>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
// Download with reqwest
|
||||
let response = reqwest::get(url).await?;
|
||||
// Download with the shared client (connect timeout). Large orig tarballs
|
||||
// can legitimately take longer than the client's default total timeout,
|
||||
// so use a generous per-request timeout for streaming downloads
|
||||
let response = crate::distro_info::http_client()
|
||||
.get(url)
|
||||
.timeout(std::time::Duration::from_secs(30 * 60))
|
||||
.send()
|
||||
.await?;
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("Failed to download '{}' : {}", url, response.status()).into());
|
||||
}
|
||||
@@ -322,7 +328,12 @@ async fn download_file_checksum(
|
||||
let mut index = 0;
|
||||
|
||||
// Target file: extract file name from URL
|
||||
let filename = Path::new(url).file_name().unwrap().to_str().unwrap();
|
||||
let filename = Path::new(url)
|
||||
.file_name()
|
||||
.and_then(|f| f.to_str())
|
||||
.ok_or_else(|| {
|
||||
format!("Could not determine a file name from URL '{url}' to download the package file")
|
||||
})?;
|
||||
let path = target_dir.join(filename);
|
||||
let mut file = File::create(path)?;
|
||||
|
||||
@@ -650,10 +661,17 @@ pub async fn pull(
|
||||
// we target the development branch, i.e. the default branch
|
||||
// Only use Ubuntu-specific branch naming if the VCS is from Launchpad
|
||||
let is_launchpad_vcs = url.contains("launchpad.net");
|
||||
let branch_name = if crate::distro_info::get_ordered_series_name(package_info.dist.as_str())
|
||||
.await?[0]
|
||||
!= *series
|
||||
{
|
||||
let series_list =
|
||||
crate::distro_info::get_ordered_series_name(package_info.dist.as_str()).await?;
|
||||
let latest_series = series_list.first().ok_or_else(|| {
|
||||
format!(
|
||||
"No series information available for distribution '{}', \
|
||||
cannot determine its development series to select the git branch. \
|
||||
The 'distro-info' package provides this data.",
|
||||
package_info.dist
|
||||
)
|
||||
})?;
|
||||
let branch_name = if latest_series != series {
|
||||
if package_info.dist == "ubuntu" && is_launchpad_vcs {
|
||||
Some(format!("{}/{}", package_info.dist, series))
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user