@@ -1164,7 +1164,7 @@ void rans_set_cpu(int opts) {
11641164unsigned char * rans_compress_to_4x16 (unsigned char * in , unsigned int in_size ,
11651165 unsigned char * out ,unsigned int * out_size ,
11661166 int order ) {
1167- if (in_size > INT_MAX ) {
1167+ if (in_size > INT_MAX || ( out && * out_size == 0 ) ) {
11681168 * out_size = 0 ;
11691169 return NULL ;
11701170 }
@@ -1177,8 +1177,10 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
11771177 * out_size = rans_compress_bound_4x16 (in_size , order );
11781178 if (* out_size == 0 )
11791179 return NULL ;
1180- if (!(out_free = out = malloc (* out_size )))
1180+ if (!(out_free = out = malloc (* out_size ))) {
1181+ * out_size = 0 ;
11811182 return NULL ;
1183+ }
11821184 }
11831185
11841186 unsigned char * out_end = out + * out_size ;
@@ -1199,11 +1201,15 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
11991201 int N = (order >>8 ) & 0xff ;
12001202 if (N == 0 ) N = 4 ; // default for compatibility with old tests
12011203
1204+ if (N > in_size )
1205+ N = in_size ;
1206+
12021207 unsigned char * transposed = malloc (in_size );
12031208 unsigned int part_len [256 ];
12041209 unsigned int idx [256 ];
12051210 if (!transposed ) {
12061211 free (out_free );
1212+ * out_size = 0 ;
12071213 return NULL ;
12081214 }
12091215 int i , j , x ;
@@ -1241,6 +1247,13 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
12411247 c_meta_len = 1 ;
12421248 * out = order & ~RANS_ORDER_NOSZ ;
12431249 c_meta_len += var_put_u32 (out + c_meta_len , out_end , in_size );
1250+ if (c_meta_len >= * out_size ) {
1251+ free (out_free );
1252+ free (transposed );
1253+ * out_size = 0 ;
1254+ return NULL ;
1255+ }
1256+
12441257 out [c_meta_len ++ ] = N ;
12451258
12461259 unsigned char * out_best = NULL ;
@@ -1249,26 +1262,33 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
12491262 out2_start = out2 = out + 7 + 5 * N ; // shares a buffer with c_meta
12501263 for (i = 0 ; i < N ; i ++ ) {
12511264 // Brute force try all methods.
1252- int j , m [] = {1 ,64 ,128 ,0 }, best_j = 0 , best_sz = in_size + 10 ;
1265+ uint8_t * r ;
1266+ int j , m [] = {1 ,64 ,128 ,0 }, best_j = 0 , best_sz = INT_MAX ;
12531267 for (j = 0 ; j < sizeof (m )/sizeof (* m ); j ++ ) {
12541268 if ((order & m [j ]) != m [j ])
12551269 continue ;
12561270
12571271 // order-1 *only*; bit check above cannot elide order-0
12581272 if ((order & RANS_ORDER_STRIPE_NO0 ) && (m [j ]& 1 ) == 0 )
12591273 continue ;
1274+
1275+ if (out2 - out > * out_size )
1276+ continue ; // an error, but caught in best_sz check later
1277+
12601278 olen2 = * out_size - (out2 - out );
1261- rans_compress_to_4x16 (transposed + idx [i ], part_len [i ],
1262- out2 , & olen2 ,
1263- m [j ] | RANS_ORDER_NOSZ
1264- | (order & RANS_ORDER_X32 ));
1265- if (best_sz > olen2 ) {
1279+ r = rans_compress_to_4x16 (transposed + idx [i ], part_len [i ],
1280+ out2 , & olen2 ,
1281+ m [j ] | RANS_ORDER_NOSZ
1282+ | (order & RANS_ORDER_X32 ));
1283+ if (r && olen2 && best_sz > olen2 ) {
12661284 best_sz = olen2 ;
12671285 best_j = j ;
12681286 if (j < sizeof (m )/sizeof (* m ) && olen2 > out_best_len ) {
12691287 unsigned char * tmp = realloc (out_best , olen2 );
12701288 if (!tmp ) {
12711289 free (out_free );
1290+ free (transposed );
1291+ * out_size = 0 ;
12721292 return NULL ;
12731293 }
12741294 out_best = tmp ;
@@ -1279,6 +1299,15 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
12791299 memcpy (out_best , out2 , olen2 );
12801300 }
12811301 }
1302+
1303+ if (best_sz == INT_MAX ) {
1304+ free (out_best );
1305+ free (out_free );
1306+ free (transposed );
1307+ * out_size = 0 ;
1308+ return NULL ;
1309+ }
1310+
12821311 if (best_j < sizeof (m )/sizeof (* m )) {
12831312 // Copy the best compression to output buffer if not current
12841313 memcpy (out2 , out_best , best_sz );
@@ -1301,6 +1330,11 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
13011330 out [0 ] = RANS_ORDER_CAT ;
13021331 c_meta_len = 1 ;
13031332 c_meta_len += var_put_u32 (& out [1 ], out_end , in_size );
1333+
1334+ if (c_meta_len + in_size > * out_size ) {
1335+ * out_size = 0 ;
1336+ return NULL ;
1337+ }
13041338 if (in_size )
13051339 memcpy (out + c_meta_len , in , in_size );
13061340 * out_size = c_meta_len + in_size ;
@@ -1329,6 +1363,11 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
13291363 // PACK 2, 4 or 8 symbols into one byte.
13301364 int pmeta_len ;
13311365 uint64_t packed_len ;
1366+ if (c_meta_len + 256 > * out_size ) {
1367+ free (out_free );
1368+ * out_size = 0 ;
1369+ return NULL ;
1370+ }
13321371 packed = hts_pack (in , in_size , out + c_meta_len , & pmeta_len , & packed_len );
13331372 if (!packed ) {
13341373 out [0 ] &= ~RANS_ORDER_PACK ;
@@ -1357,6 +1396,7 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
13571396 c_rmeta_len = in_size + 257 ;
13581397 if (!(meta = malloc (c_rmeta_len ))) {
13591398 free (out_free );
1399+ * out_size = 0 ;
13601400 return NULL ;
13611401 }
13621402
@@ -1380,8 +1420,23 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
13801420 // Compress lengths with O0 and literals with O0/O1 ("order" param)
13811421 int sz = var_put_u32 (out + c_meta_len , out_end , rmeta_len * 2 ), sz2 ;
13821422 sz += var_put_u32 (out + c_meta_len + sz , out_end , rle_len );
1423+ if ((c_meta_len + sz + 5 ) > * out_size ) {
1424+ free (out_free );
1425+ free (rle );
1426+ free (meta );
1427+ free (packed );
1428+ * out_size = 0 ;
1429+ return NULL ;
1430+ }
13831431 c_rmeta_len = * out_size - (c_meta_len + sz + 5 );
1384- rans_enc_func (do_simd , 0 )(meta , rmeta_len , out + c_meta_len + sz + 5 , & c_rmeta_len );
1432+ if (!rans_enc_func (do_simd , 0 )(meta , rmeta_len , out + c_meta_len + sz + 5 , & c_rmeta_len )) {
1433+ free (out_free );
1434+ free (rle );
1435+ free (meta );
1436+ free (packed );
1437+ * out_size = 0 ;
1438+ return NULL ;
1439+ }
13851440 if (c_rmeta_len < rmeta_len ) {
13861441 sz2 = var_put_u32 (out + c_meta_len + sz , out_end , c_rmeta_len );
13871442 memmove (out + c_meta_len + sz + sz2 , out + c_meta_len + sz + 5 , c_rmeta_len );
@@ -1404,17 +1459,36 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
14041459 out [0 ] &= ~RANS_ORDER_RLE ;
14051460 }
14061461
1462+ if (c_meta_len > * out_size ) {
1463+ free (rle );
1464+ free (packed );
1465+ * out_size = 0 ;
1466+ return NULL ;
1467+ }
1468+
14071469 * out_size -= c_meta_len ;
14081470 if (order && in_size < 8 ) {
14091471 out [0 ] &= ~1 ;
14101472 order &= ~1 ;
14111473 }
14121474
1413- rans_enc_func (do_simd , order )(in , in_size , out + c_meta_len , out_size );
1475+ if (!rans_enc_func (do_simd , order )(in , in_size , out + c_meta_len , out_size )) {
1476+ free (rle );
1477+ free (packed );
1478+ * out_size = 0 ;
1479+ return NULL ;
1480+ }
14141481
14151482 if (* out_size >= in_size ) {
14161483 out [0 ] &= ~3 ;
14171484 out [0 ] |= RANS_ORDER_CAT | no_size ;
1485+
1486+ if (out + c_meta_len + in_size > out_end ) {
1487+ free (rle );
1488+ free (packed );
1489+ * out_size = 0 ;
1490+ return NULL ;
1491+ }
14181492 if (in_size )
14191493 memcpy (out + c_meta_len , in , in_size );
14201494 * out_size = in_size ;
0 commit comments