Merge pull request #1168 from Young-X/fix_dev

Fix multiple potential vulnerabilities and bugs
This commit is contained in:
Even Rouault 2018-12-07 21:27:38 +01:00 committed by GitHub
commit e7640f58f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 27 deletions

View File

@ -41,6 +41,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#ifdef OPJ_HAVE_LIBTIFF #ifdef OPJ_HAVE_LIBTIFF
#include <tiffio.h> #include <tiffio.h>
@ -98,15 +99,10 @@ struct tga_header {
}; };
#endif /* INFORMATION_ONLY */ #endif /* INFORMATION_ONLY */
static unsigned short get_ushort(unsigned short val) /* Returns a ushort from a little-endian serialized value */
static unsigned short get_tga_ushort(const unsigned char *data)
{ {
return data[0] | (data[1] << 8);
#ifdef OPJ_BIG_ENDIAN
return (((val & 0xff) << 8) + (val >> 8));
#else
return (val);
#endif
} }
#define TGA_HEADER_SIZE 18 #define TGA_HEADER_SIZE 18
@ -135,15 +131,15 @@ static int tga_readheader(FILE *fp, unsigned int *bits_per_pixel,
id_len = (unsigned char)tga[0]; id_len = (unsigned char)tga[0];
cmap_type = (unsigned char)tga[1]; cmap_type = (unsigned char)tga[1];
image_type = (unsigned char)tga[2]; image_type = (unsigned char)tga[2];
cmap_index = get_ushort(*(unsigned short*)(&tga[3])); cmap_index = get_tga_ushort(*(unsigned short*)(&tga[3]));
cmap_len = get_ushort(*(unsigned short*)(&tga[5])); cmap_len = get_tga_ushort(*(unsigned short*)(&tga[5]));
cmap_entry_size = (unsigned char)tga[7]; cmap_entry_size = (unsigned char)tga[7];
x_origin = get_ushort(*(unsigned short*)(&tga[8])); x_origin = get_tga_ushort(*(unsigned short*)(&tga[8]));
y_origin = get_ushort(*(unsigned short*)(&tga[10])); y_origin = get_tga_ushort(*(unsigned short*)(&tga[10]));
image_w = get_ushort(*(unsigned short*)(&tga[12])); image_w = get_tga_ushort(*(unsigned short*)(&tga[12]));
image_h = get_ushort(*(unsigned short*)(&tga[14])); image_h = get_tga_ushort(*(unsigned short*)(&tga[14]));
pixel_depth = (unsigned char)tga[16]; pixel_depth = (unsigned char)tga[16];
image_desc = (unsigned char)tga[17]; image_desc = (unsigned char)tga[17];
@ -333,6 +329,24 @@ opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters)
color_space = CLRSPC_SRGB; color_space = CLRSPC_SRGB;
} }
/* If the declared file size is > 10 MB, check that the file is big */
/* enough to avoid excessive memory allocations */
if (image_height != 0 && image_width > 10000000 / image_height / numcomps) {
char ch;
OPJ_UINT64 expected_file_size =
(OPJ_UINT64)image_width * image_height * numcomps;
long curpos = ftell(f);
if (expected_file_size > (OPJ_UINT64)INT_MAX) {
expected_file_size = (OPJ_UINT64)INT_MAX;
}
fseek(f, (long)expected_file_size - 1, SEEK_SET);
if (fread(&ch, 1, 1, f) != 1) {
fclose(f);
return NULL;
}
fseek(f, curpos, SEEK_SET);
}
subsampling_dx = parameters->subsampling_dx; subsampling_dx = parameters->subsampling_dx;
subsampling_dy = parameters->subsampling_dy; subsampling_dy = parameters->subsampling_dy;
@ -444,7 +458,7 @@ int imagetotga(opj_image_t * image, const char *outfile)
{ {
int width, height, bpp, x, y; int width, height, bpp, x, y;
opj_bool write_alpha; opj_bool write_alpha;
int i, adjustR, adjustG, adjustB; int i, adjustR, adjustG = 0, adjustB = 0;
unsigned int alpha_channel; unsigned int alpha_channel;
float r, g, b, a; float r, g, b, a;
unsigned char value; unsigned char value;
@ -485,8 +499,10 @@ int imagetotga(opj_image_t * image, const char *outfile)
scale = 255.0f / (float)((1 << image->comps[0].prec) - 1); scale = 255.0f / (float)((1 << image->comps[0].prec) - 1);
adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
if (image->numcomps >= 3) {
adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
}
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
unsigned int index = y * width; unsigned int index = y * width;
@ -1862,6 +1878,15 @@ opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters)
return NULL; return NULL;
} }
/* This limitation could be removed by making sure to use size_t below */
if (header_info.height != 0 &&
header_info.width > INT_MAX / header_info.height) {
fprintf(stderr, "pnmtoimage:Image %dx%d too big!\n",
header_info.width, header_info.height);
fclose(fp);
return NULL;
}
format = header_info.format; format = header_info.format;
switch (format) { switch (format) {

View File

@ -952,8 +952,9 @@ static int parse_cmdline_encoder(int argc, char **argv,
case 'b': { /* code-block dimension */ case 'b': { /* code-block dimension */
int cblockw_init = 0, cblockh_init = 0; int cblockw_init = 0, cblockh_init = 0;
sscanf(opj_optarg, "%d,%d", &cblockw_init, &cblockh_init); sscanf(opj_optarg, "%d,%d", &cblockw_init, &cblockh_init);
if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 if (cblockw_init > 1024 || cblockw_init < 4 ||
|| cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) { cblockh_init > 1024 || cblockh_init < 4 ||
cblockw_init * cblockh_init > 4096) {
fprintf(stderr, fprintf(stderr,
"!! Size of code_block error (option -b) !!\n\nRestriction :\n" "!! Size of code_block error (option -b) !!\n\nRestriction :\n"
" * width*height<=4096\n * 4<=width,height<= 1024\n\n"); " * width*height<=4096\n * 4<=width,height<= 1024\n\n");

View File

@ -748,6 +748,9 @@ static void opj_get_encoding_parameters(const opj_image_t *p_image,
/* position in x and y of tile */ /* position in x and y of tile */
OPJ_UINT32 p, q; OPJ_UINT32 p, q;
/* non-corrected (in regard to image offset) tile offset */
OPJ_UINT32 l_tx0, l_ty0;
/* preconditions */ /* preconditions */
assert(p_cp != 00); assert(p_cp != 00);
assert(p_image != 00); assert(p_image != 00);
@ -763,14 +766,14 @@ static void opj_get_encoding_parameters(const opj_image_t *p_image,
q = p_tileno / p_cp->tw; q = p_tileno / p_cp->tw;
/* find extent of tile */ /* find extent of tile */
*p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx), l_tx0 = p_cp->tx0 + p *
(OPJ_INT32)p_image->x0); p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */
*p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx), *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0);
(OPJ_INT32)p_image->x1); *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1);
*p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy), l_ty0 = p_cp->ty0 + q *
(OPJ_INT32)p_image->y0); p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */
*p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy), *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0);
(OPJ_INT32)p_image->y1); *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1);
/* max precision is 0 (can only grow) */ /* max precision is 0 (can only grow) */
*p_max_prec = 0; *p_max_prec = 0;

View File

@ -223,6 +223,14 @@ static bool pi_next_rpcl(opj_pi_iterator_t * pi)
rpx = res->pdx + levelnox; rpx = res->pdx + levelnox;
rpy = res->pdy + levelnoy; rpy = res->pdy + levelnoy;
rpz = res->pdz + levelnoz; rpz = res->pdz + levelnoz;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy ||
rpz >= 31 || ((comp->dz << rpz) >> rpz) != comp->dz) {
continue;
}
if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 &&
(trx0 << levelnox) % (1 << rpx)))) { (trx0 << levelnox) % (1 << rpx)))) {
continue; continue;
@ -329,6 +337,14 @@ static bool pi_next_pcrl(opj_pi_iterator_t * pi)
rpx = res->pdx + levelnox; rpx = res->pdx + levelnox;
rpy = res->pdy + levelnoy; rpy = res->pdy + levelnoy;
rpz = res->pdz + levelnoz; rpz = res->pdz + levelnoz;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy ||
rpz >= 31 || ((comp->dz << rpz) >> rpz) != comp->dz) {
continue;
}
if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 &&
(trx0 << levelnox) % (1 << rpx)))) { (trx0 << levelnox) % (1 << rpx)))) {
continue; continue;
@ -432,6 +448,14 @@ static bool pi_next_cprl(opj_pi_iterator_t * pi)
rpx = res->pdx + levelnox; rpx = res->pdx + levelnox;
rpy = res->pdy + levelnoy; rpy = res->pdy + levelnoy;
rpz = res->pdz + levelnoz; rpz = res->pdz + levelnoz;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy ||
rpz >= 31 || ((comp->dz << rpz) >> rpz) != comp->dz) {
continue;
}
if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 &&
(trx0 << levelnox) % (1 << rpx)))) { (trx0 << levelnox) % (1 << rpx)))) {
continue; continue;

View File

@ -85,6 +85,12 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi);
========================================================== ==========================================================
*/ */
static void opj_pi_emit_error(opj_pi_iterator_t * pi, const char* msg)
{
(void)pi;
(void)msg;
}
static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)
{ {
opj_pi_comp_t *comp = NULL; opj_pi_comp_t *comp = NULL;
@ -114,6 +120,11 @@ static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)
for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
pi->step_c + pi->precno * pi->step_p; pi->step_c + pi->precno * pi->step_p;
/* Avoids index out of bounds access with include*/
if (index >= pi->include_size) {
opj_pi_emit_error(pi, "Invalid access to pi->include");
return OPJ_FALSE;
}
if (!pi->include[index]) { if (!pi->include[index]) {
pi->include[index] = 1; pi->include[index] = 1;
return OPJ_TRUE; return OPJ_TRUE;
@ -156,6 +167,11 @@ static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi)
for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
pi->step_c + pi->precno * pi->step_p; pi->step_c + pi->precno * pi->step_p;
/* Avoids index out of bounds access with include*/
if (index >= pi->include_size) {
opj_pi_emit_error(pi, "Invalid access to pi->include");
return OPJ_FALSE;
}
if (!pi->include[index]) { if (!pi->include[index]) {
pi->include[index] = 1; pi->include[index] = 1;
return OPJ_TRUE; return OPJ_TRUE;
@ -224,6 +240,13 @@ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi)
try1 = int_ceildiv(pi->ty1, comp->dy << levelno); try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
rpx = res->pdx + levelno; rpx = res->pdx + levelno;
rpy = res->pdy + levelno; rpy = res->pdy + levelno;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
((try0 << levelno) % (1 << rpy))))) { ((try0 << levelno) % (1 << rpy))))) {
continue; continue;
@ -249,6 +272,11 @@ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi)
for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
pi->step_c + pi->precno * pi->step_p; pi->step_c + pi->precno * pi->step_p;
/* Avoids index out of bounds access with include*/
if (index >= pi->include_size) {
opj_pi_emit_error(pi, "Invalid access to pi->include");
return OPJ_FALSE;
}
if (!pi->include[index]) { if (!pi->include[index]) {
pi->include[index] = 1; pi->include[index] = 1;
return OPJ_TRUE; return OPJ_TRUE;
@ -317,6 +345,13 @@ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi)
try1 = int_ceildiv(pi->ty1, comp->dy << levelno); try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
rpx = res->pdx + levelno; rpx = res->pdx + levelno;
rpy = res->pdy + levelno; rpy = res->pdy + levelno;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
((try0 << levelno) % (1 << rpy))))) { ((try0 << levelno) % (1 << rpy))))) {
continue; continue;
@ -342,6 +377,11 @@ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi)
for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
pi->step_c + pi->precno * pi->step_p; pi->step_c + pi->precno * pi->step_p;
/* Avoids index out of bounds access with include*/
if (index >= pi->include_size) {
opj_pi_emit_error(pi, "Invalid access to pi->include");
return OPJ_FALSE;
}
if (!pi->include[index]) { if (!pi->include[index]) {
pi->include[index] = 1; pi->include[index] = 1;
return OPJ_TRUE; return OPJ_TRUE;
@ -408,6 +448,13 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi)
try1 = int_ceildiv(pi->ty1, comp->dy << levelno); try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
rpx = res->pdx + levelno; rpx = res->pdx + levelno;
rpy = res->pdy + levelno; rpy = res->pdy + levelno;
/* To avoid divisions by zero / undefined behaviour on shift */
if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
((try0 << levelno) % (1 << rpy))))) { ((try0 << levelno) % (1 << rpy))))) {
continue; continue;
@ -433,6 +480,11 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi)
for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
pi->step_c + pi->precno * pi->step_p; pi->step_c + pi->precno * pi->step_p;
/* Avoids index out of bounds access with include*/
if (index >= pi->include_size) {
opj_pi_emit_error(pi, "Invalid access to pi->include");
return OPJ_FALSE;
}
if (!pi->include[index]) { if (!pi->include[index]) {
pi->include[index] = 1; pi->include[index] = 1;
return OPJ_TRUE; return OPJ_TRUE;