Fix double free of cinfo->master caused by the extension framework modifications
There was an oversight in the extension framework. jpeg_start_compress() can be called multiple times between the time that a compress structure is created and the time it is destroyed. If this happened, then the following sequence would occur: -- heap alloc of master struct within jpeg_create_compress() -- heap free of master struct within jinit_c_master_control() -- static alloc of extended master struct (JPOOL_IMAGE) within jinit_c_master_control() -- free extended master struct in jpeg_finish_compress() -- jinit_c_master_control() now sees that cinfo->master is set and tries to free it, even though it has already been freed. Chaos ensues. The fix involved breaking out the extended master struct into a header so that jpeg_create_compress() can go ahead and allocate it to the correct size, thus eliminating the need to free and reallocate it in jinit_c_master_control(). Further, the master struct is now created in the permanent pool, so it will survive until the compression struct is destroyed. Further, jinit_c_master_control() now resets all fields in the master struct that are not related to the extension parameters.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h"
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -97,8 +98,10 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
|
||||
* here. It is later reallocated by jinit_c_master_control().
|
||||
*/
|
||||
cinfo->master = (struct jpeg_comp_master *)
|
||||
jpeg_get_small ((j_common_ptr) cinfo, sizeof(struct jpeg_comp_master));
|
||||
MEMZERO(cinfo->master, sizeof(struct jpeg_comp_master));
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(my_comp_master));
|
||||
MEMZERO(cinfo->master, sizeof(my_comp_master));
|
||||
|
||||
cinfo->master->compress_profile = JCP_MAX_COMPRESSION;
|
||||
}
|
||||
|
||||
|
||||
49
jcmaster.c
49
jcmaster.c
@@ -21,42 +21,7 @@
|
||||
#include "jpeglib.h"
|
||||
#include "jpegcomp.h"
|
||||
#include "jmemsys.h"
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef enum {
|
||||
main_pass, /* input data, also do first output step */
|
||||
huff_opt_pass, /* Huffman code optimization pass */
|
||||
output_pass, /* data output pass */
|
||||
trellis_pass /* trellis quantization pass */
|
||||
} c_pass_type;
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_comp_master pub; /* public fields */
|
||||
|
||||
c_pass_type pass_type; /* the type of the current pass */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
int total_passes; /* total # of passes needed */
|
||||
|
||||
int scan_number; /* current index in scan_info[] */
|
||||
|
||||
/* fields for scan optimisation */
|
||||
int pass_number_scan_opt_base; /* pass number where scan optimization begins */
|
||||
unsigned char * scan_buffer[64]; /* buffer for a given scan */
|
||||
unsigned long scan_size[64]; /* size for a given scan */
|
||||
int actual_Al[64]; /* actual value of Al used for a scan */
|
||||
unsigned long best_cost; /* bit count for best frequency split */
|
||||
int best_freq_split_idx_luma; /* index for best frequency split (luma) */
|
||||
int best_freq_split_idx_chroma; /* index for best frequency split (chroma) */
|
||||
int best_Al_luma; /* best value for Al found in scan search (luma) */
|
||||
int best_Al_chroma; /* best value for Al found in scan search (luma) */
|
||||
boolean interleave_chroma_dc; /* indicate whether to interleave chroma DC scans */
|
||||
struct jpeg_destination_mgr * saved_dest; /* saved value of cinfo->dest */
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master * my_master_ptr;
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -919,21 +884,13 @@ finish_pass_master (j_compress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
|
||||
{
|
||||
my_master_ptr master;
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
master = (my_master_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
sizeof(my_comp_master));
|
||||
if (cinfo->master) {
|
||||
MEMCOPY(&master->pub, cinfo->master, sizeof(struct jpeg_comp_master));
|
||||
jpeg_free_small((j_common_ptr) cinfo, cinfo->master,
|
||||
sizeof(struct jpeg_comp_master));
|
||||
}
|
||||
cinfo->master = (struct jpeg_comp_master *) master;
|
||||
master->pub.prepare_for_pass = prepare_for_pass;
|
||||
master->pub.pass_startup = pass_startup;
|
||||
master->pub.finish_pass = finish_pass_master;
|
||||
master->pub.is_last_pass = FALSE;
|
||||
master->pub.call_pass_startup = FALSE;
|
||||
|
||||
/* Validate parameters, determine derived values */
|
||||
initial_setup(cinfo, transcode_only);
|
||||
|
||||
47
jcmaster.h
Normal file
47
jcmaster.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* jcmaster.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* mozjpeg Modifications:
|
||||
* Copyright (C) 2014, Mozilla Corporation.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the master control structures for the JPEG compressor.
|
||||
*/
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef enum {
|
||||
main_pass, /* input data, also do first output step */
|
||||
huff_opt_pass, /* Huffman code optimization pass */
|
||||
output_pass, /* data output pass */
|
||||
trellis_pass /* trellis quantization pass */
|
||||
} c_pass_type;
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_comp_master pub; /* public fields */
|
||||
|
||||
c_pass_type pass_type; /* the type of the current pass */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
int total_passes; /* total # of passes needed */
|
||||
|
||||
int scan_number; /* current index in scan_info[] */
|
||||
|
||||
/* fields for scan optimisation */
|
||||
int pass_number_scan_opt_base; /* pass number where scan optimization begins */
|
||||
unsigned char * scan_buffer[64]; /* buffer for a given scan */
|
||||
unsigned long scan_size[64]; /* size for a given scan */
|
||||
int actual_Al[64]; /* actual value of Al used for a scan */
|
||||
unsigned long best_cost; /* bit count for best frequency split */
|
||||
int best_freq_split_idx_luma; /* index for best frequency split (luma) */
|
||||
int best_freq_split_idx_chroma; /* index for best frequency split (chroma) */
|
||||
int best_Al_luma; /* best value for Al found in scan search (luma) */
|
||||
int best_Al_chroma; /* best value for Al found in scan search (luma) */
|
||||
boolean interleave_chroma_dc; /* indicate whether to interleave chroma DC scans */
|
||||
struct jpeg_destination_mgr * saved_dest; /* saved value of cinfo->dest */
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master * my_master_ptr;
|
||||
Reference in New Issue
Block a user