Skip to content

Commit c35d339

Browse files
committed
Protection from attempting to do SIMD rans encoding on small data
We can't just change do_simd as we may then have a combination of SIMD (pack or rle-meta) and non-SIMD (rle-meta or rle-data). So instead we remove the ability to do SIMD and call again. This only happens when we have large blocks of data that enable SIMD mode which then turn out to be heavily compressible after PACK or RLE to yield a small sub-stream which isn't SIMD compressible.
1 parent ce66e5f commit c35d339

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

htscodecs/rANS_static4x16pr.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,10 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
11691169
return NULL;
11701170
}
11711171

1172+
int orig_order = order;
1173+
int orig_in_size = in_size;
1174+
unsigned char *orig_in = in;
1175+
11721176
unsigned int c_meta_len;
11731177
uint8_t *meta = NULL, *rle = NULL, *packed = NULL;
11741178
uint8_t *out_free = NULL;
@@ -1385,6 +1389,14 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
13851389
int sz = var_put_u32(out+c_meta_len, out_end, in_size);
13861390
c_meta_len += sz;
13871391
*out_size -= sz;
1392+
1393+
if (do_simd && in_size < 32) {
1394+
free(packed);
1395+
return rans_compress_to_4x16(orig_in, orig_in_size,
1396+
out, out_size,
1397+
orig_order & ~(RANS_ORDER_X32 |
1398+
RANS_ORDER_SIMD_AUTO));
1399+
}
13881400
}
13891401
} else if (do_pack) {
13901402
out[0] &= ~RANS_ORDER_PACK;
@@ -1430,6 +1442,15 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
14301442
return NULL;
14311443
}
14321444
c_rmeta_len = *out_size - (c_meta_len+sz+5);
1445+
if (do_simd && (rmeta_len < 32 || rle_len < 32)) {
1446+
free(packed);
1447+
free(rle);
1448+
free(meta);
1449+
return rans_compress_to_4x16(orig_in, orig_in_size,
1450+
out, out_size,
1451+
orig_order & ~(RANS_ORDER_X32 |
1452+
RANS_ORDER_SIMD_AUTO));
1453+
}
14331454
if (!rans_enc_func(do_simd, 0)(meta, rmeta_len, out+c_meta_len+sz+5, &c_rmeta_len)) {
14341455
free(out_free);
14351456
free(rle);
@@ -1496,13 +1517,31 @@ unsigned char *rans_compress_to_4x16(unsigned char *in, unsigned int in_size,
14961517
if (in_size)
14971518
memcpy(out+c_meta_len, in, in_size);
14981519
*out_size = in_size;
1499-
}
1520+
}
15001521

15011522
free(rle);
15021523
free(packed);
15031524

15041525
*out_size += c_meta_len;
15051526

1527+
// Validation mode
1528+
#ifdef VALIDATE_RANS
1529+
unsigned int decoded_size = orig_in_size;
1530+
unsigned char *decoded = malloc(decoded_size);
1531+
decoded = rans_uncompress_to_4x16(out, *out_size,
1532+
decoded, &decoded_size);
1533+
if (!decoded ||
1534+
decoded_size != orig_in_size ||
1535+
memcmp(orig_in, decoded, orig_in_size) != 0) {
1536+
fprintf(stderr, "rans round trip failed for order %d. Written to fd 5\n", orig_order);
1537+
if (write(5, orig_in, orig_in_size) < 0)
1538+
abort();
1539+
abort();
1540+
}
1541+
free(decoded);
1542+
#endif
1543+
1544+
15061545
return out;
15071546
}
15081547

0 commit comments

Comments
 (0)