mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-05 10:10:46 +00:00
fix(update): read GitHub API answers up to a 16 MiB cap
get_api shared the 4 MiB limit for small answers. A launcher version list of 100 releases can pass that: SolidCraft's was 6.5 MB (craft-launcher#1021). Other small requests keep 4 MiB.
This commit is contained in:
1 parent
2b8bd856ce
commit
f0b5b22dce
1 file changed
+16
-1
@@ -11,6 +11,8 @@ use sha2::{Digest, Sha256};
|
||||
|
||||
/// Largest JSON or text answer we read.
|
||||
const MAX_SMALL: u64 = 4 << 20;
|
||||
/// Largest GitHub API answer we read: 100 releases of an app with 49 assets are about 10 MB.
|
||||
const MAX_API: u64 = 16 << 20;
|
||||
|
||||
/// What a GET of a small resource produced.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -154,7 +156,7 @@ impl Http {
|
||||
match status {
|
||||
200 => {
|
||||
let etag = header("etag");
|
||||
let text = read_text_capped(&mut resp, MAX_SMALL).map_err(|e| format!("unreadable answer from GitHub ({e})"))?;
|
||||
let text = read_text_capped(&mut resp, MAX_API).map_err(|e| format!("unreadable answer from GitHub ({e})"))?;
|
||||
Ok(Fetched::Body { text, etag })
|
||||
}
|
||||
304 => Ok(Fetched::NotModified),
|
||||
@@ -996,6 +998,19 @@ pub(crate) mod tests {
|
||||
assert_eq!(http.get_feed(&url).unwrap(), "{\"ok\":true}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_long_release_list_is_read_up_to_the_api_cap() {
|
||||
// SolidCraft's list of 100 releases was 6.5 MB, past MAX_SMALL (craft-launcher#1021).
|
||||
let long = vec![b' '; (MAX_SMALL as usize) + 1024];
|
||||
let (url, _) = serve(long.clone(), vec![Reply::Full]);
|
||||
let http = Http::new(crate::TEST_AGENT).unwrap();
|
||||
assert!(matches!(http.get_api(&url, None), Ok(Fetched::Body { text, .. }) if text.len() == long.len()));
|
||||
// Past MAX_API it is refused outright, not truncated and parsed.
|
||||
let (url, _) = serve(vec![b' '; (MAX_API as usize) + 1024], vec![Reply::Full]);
|
||||
let err = http.get_api(&url, None).unwrap_err();
|
||||
assert!(err.contains("larger than"), "{err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_gzip_bomb_answer_is_refused_before_parsing() {
|
||||
// A few hundred bytes on the wire that decode to more than MAX_SMALL. ureq's own limit
|
||||
|
||||
Reference in new issue
Block a user