|
32 | 32 | // which is exactly what is exported by the [`crate::tar::export`] process. |
33 | 33 |
|
34 | 34 | use crate::container::store::LayerProgress; |
| 35 | +use crate::generic_decompress::{ |
| 36 | + Decompressable, GzipDecompressor, TransparentDecompressor, ZstdDecompressor, |
| 37 | +}; |
35 | 38 |
|
36 | 39 | use super::*; |
37 | 40 | use containers_image_proxy::{ImageProxy, OpenedImage}; |
@@ -191,57 +194,6 @@ pub async fn unencapsulate(repo: &ostree::Repo, imgref: &OstreeImageReference) - |
191 | 194 | importer.unencapsulate().await |
192 | 195 | } |
193 | 196 |
|
194 | | -trait Decompressable: Read + Send + 'static { |
195 | | - fn get_inner_mut(&mut self) -> &mut (dyn Read); |
196 | | -} |
197 | | - |
198 | | -// TransparentDecompressor |
199 | | - |
200 | | -struct TransparentDecompressor<R: Read + Send + 'static>(R); |
201 | | - |
202 | | -impl<R: Read + Send + 'static> Read for TransparentDecompressor<R> { |
203 | | - fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { |
204 | | - self.0.read(buf) |
205 | | - } |
206 | | -} |
207 | | - |
208 | | -impl<R: Read + Send + 'static> Decompressable for TransparentDecompressor<R> { |
209 | | - fn get_inner_mut(&mut self) -> &mut (dyn Read) { |
210 | | - &mut self.0 |
211 | | - } |
212 | | -} |
213 | | - |
214 | | -// GzipDecompressor |
215 | | - |
216 | | -struct GzipDecompressor<R: std::io::BufRead>(flate2::bufread::GzDecoder<R>); |
217 | | - |
218 | | -impl<R: std::io::BufRead + Send + 'static> Read for GzipDecompressor<R> { |
219 | | - fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { |
220 | | - self.0.read(buf) |
221 | | - } |
222 | | -} |
223 | | - |
224 | | -impl<R: std::io::BufRead + Send + 'static> Decompressable for GzipDecompressor<R> { |
225 | | - fn get_inner_mut(&mut self) -> &mut (dyn Read) { |
226 | | - self.0.get_mut() |
227 | | - } |
228 | | -} |
229 | | - |
230 | | -// ZstdDecompressor |
231 | | -struct ZstdDecompressor<'a, R: std::io::BufRead>(zstd::stream::read::Decoder<'a, R>); |
232 | | - |
233 | | -impl<'a: 'static, R: std::io::BufRead + Send + 'static> Read for ZstdDecompressor<'a, R> { |
234 | | - fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { |
235 | | - self.0.read(buf) |
236 | | - } |
237 | | -} |
238 | | - |
239 | | -impl<'a: 'static, R: std::io::BufRead + Send + 'static> Decompressable for ZstdDecompressor<'a, R> { |
240 | | - fn get_inner_mut(&mut self) -> &mut (dyn Read) { |
241 | | - self.0.get_mut() |
242 | | - } |
243 | | -} |
244 | | - |
245 | 197 | pub(crate) struct Decompressor { |
246 | 198 | inner: Box<dyn Decompressable>, |
247 | 199 | finished: bool, |
@@ -429,4 +381,26 @@ mod tests { |
429 | 381 | let d = Decompressor::new(&oci_image::MediaType::ImageLayerZstd, empty).unwrap(); |
430 | 382 | drop(d) |
431 | 383 | } |
| 384 | + |
| 385 | + #[test] |
| 386 | + fn test_gzip_decompressor_with_garbage_input() { |
| 387 | + let garbage = b"This is not valid gzip data"; |
| 388 | + let mut d = Decompressor::new(&oci_image::MediaType::ImageLayerGzip, &garbage[..]).unwrap(); |
| 389 | + let mut buf = [0u8; 32]; |
| 390 | + let e = d.read(&mut buf).unwrap_err(); |
| 391 | + assert!(matches!(e.kind(), std::io::ErrorKind::InvalidInput)); |
| 392 | + assert_eq!(e.to_string(), "invalid gzip header".to_string()); |
| 393 | + drop(d) |
| 394 | + } |
| 395 | + |
| 396 | + #[test] |
| 397 | + fn test_zstd_decompressor_with_garbage_input() { |
| 398 | + let garbage = b"This is not valid zstd data"; |
| 399 | + let mut d = Decompressor::new(&oci_image::MediaType::ImageLayerZstd, &garbage[..]).unwrap(); |
| 400 | + let mut buf = [0u8; 32]; |
| 401 | + let e = d.read(&mut buf).unwrap_err(); |
| 402 | + assert!(matches!(e.kind(), std::io::ErrorKind::Other)); |
| 403 | + assert_eq!(e.to_string(), "Unknown frame descriptor".to_string()); |
| 404 | + drop(d) |
| 405 | + } |
432 | 406 | } |
0 commit comments