Error handling of corrupted JPEG files

This commit is contained in:
Matteo Paonessa 2023-06-10 14:29:42 +02:00
parent 528bbaed0c
commit b88a818262
5 changed files with 59 additions and 6 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "libcaesium" name = "libcaesium"
version = "0.11.0" version = "0.11.1"
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"] authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
edition = "2021" edition = "2021"
categories = ["multimedia::images"] categories = ["multimedia::images"]

View File

@ -11,6 +11,8 @@ use libc::free;
use crate::resize::resize; use crate::resize::resize;
use crate::CSParameters; use crate::CSParameters;
static mut JPEG_ERROR: c_int = 0;
pub fn compress( pub fn compress(
input_path: String, input_path: String,
output_path: String, output_path: String,
@ -58,7 +60,10 @@ unsafe fn lossless(
let mut dst_err = mem::zeroed(); let mut dst_err = mem::zeroed();
src_info.common.err = jpeg_std_error(&mut src_err); src_info.common.err = jpeg_std_error(&mut src_err);
(*src_info.common.err).error_exit = Option::Some(error_handler);
dst_info.common.err = jpeg_std_error(&mut dst_err); dst_info.common.err = jpeg_std_error(&mut dst_err);
(*dst_info.common.err).error_exit = Option::Some(error_handler);
jpeg_create_decompress(&mut src_info); jpeg_create_decompress(&mut src_info);
jpeg_create_compress(&mut dst_info); jpeg_create_compress(&mut dst_info);
@ -72,7 +77,13 @@ unsafe fn lossless(
} }
} }
jpeg_read_header(&mut src_info, i32::from(true)); jpeg_read_header(&mut src_info, true as boolean);
if JPEG_ERROR == 11 {
jpeg_destroy_decompress(&mut src_info);
jpeg_create_compress(&mut dst_info);
return Err(io::Error::new(io::ErrorKind::Other, format!("Decompress internal error: {}", JPEG_ERROR)));
}
let src_coef_arrays = jpeg_read_coefficients(&mut src_info); let src_coef_arrays = jpeg_read_coefficients(&mut src_info);
jpeg_copy_critical_parameters(&src_info, &mut dst_info); jpeg_copy_critical_parameters(&src_info, &mut dst_info);
let dst_coef_arrays = src_coef_arrays; let dst_coef_arrays = src_coef_arrays;
@ -121,7 +132,9 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<Vec<u8>,
let mut dst_err = mem::zeroed(); let mut dst_err = mem::zeroed();
src_info.common.err = jpeg_std_error(&mut src_err); src_info.common.err = jpeg_std_error(&mut src_err);
(*src_info.common.err).error_exit = Option::Some(error_handler);
dst_info.common.err = jpeg_std_error(&mut dst_err); dst_info.common.err = jpeg_std_error(&mut dst_err);
(*dst_info.common.err).error_exit = Option::Some(error_handler);
jpeg_create_decompress(&mut src_info); jpeg_create_decompress(&mut src_info);
jpeg_create_compress(&mut dst_info); jpeg_create_compress(&mut dst_info);
@ -137,6 +150,12 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<Vec<u8>,
jpeg_read_header(&mut src_info, true as boolean); jpeg_read_header(&mut src_info, true as boolean);
if JPEG_ERROR == 11 {
jpeg_destroy_decompress(&mut src_info);
jpeg_create_compress(&mut dst_info);
return Err(io::Error::new(io::ErrorKind::Other, format!("Decompress internal error: {}", JPEG_ERROR)));
}
let width = src_info.image_width; let width = src_info.image_width;
let height = src_info.image_height; let height = src_info.image_height;
let color_space = src_info.jpeg_color_space; let color_space = src_info.jpeg_color_space;
@ -257,3 +276,7 @@ fn save_metadata(
image_buffer image_buffer
} }
} }
unsafe extern "C" fn error_handler(cinfo: &mut jpeg_common_struct) {
JPEG_ERROR = (*cinfo.err).msg_code;
}

View File

@ -1,12 +1,16 @@
use caesium::{compress_to_size, initialize_parameters}; use caesium::{compress, initialize_parameters};
use std::env; use std::env;
use std::process::ExitCode;
fn main() { fn main() -> ExitCode {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let input = args[1].clone(); let input = args[1].clone();
let output = args[2].clone(); let output = args[2].clone();
let mut parameters = initialize_parameters(); let parameters = initialize_parameters();
compress_to_size(input, output, &mut parameters, args[3].clone().parse().unwrap()).unwrap(); match compress(input, output, &parameters) {
Ok(_) => ExitCode::SUCCESS,
Err(_) => ExitCode::FAILURE,
}
} }

View File

@ -96,6 +96,19 @@ fn compress_10() {
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
#[test]
fn compress_corrupted_lossy() {
let output = "tests/samples/output/corrupted_lossy.jpg";
initialize(output);
let mut pars = caesium::initialize_parameters();
pars.jpeg.quality = 50;
assert!(caesium::compress(
String::from("tests/samples/corrupted.jpg"),
String::from(output),
&pars,
).is_err())
}
#[test] #[test]
fn optimize_jpeg() { fn optimize_jpeg() {
let output = "tests/samples/output/compressed_optimized_드림캐쳐.jpg"; let output = "tests/samples/output/compressed_optimized_드림캐쳐.jpg";
@ -119,6 +132,19 @@ fn optimize_jpeg() {
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
#[test]
fn compress_corrupted_lossless() {
let output = "tests/samples/output/corrupted_lossless.jpg";
initialize(output);
let mut pars = caesium::initialize_parameters();
pars.optimize = true;
assert!(caesium::compress(
String::from("tests/samples/corrupted.jpg"),
String::from(output),
&pars,
).is_err());
}
#[test] #[test]
fn downscale_exact() { fn downscale_exact() {
let output = "tests/samples/output/downscale_800_600.jpg"; let output = "tests/samples/output/downscale_800_600.jpg";

BIN
tests/samples/corrupted.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB