Fix an integer overflow bug in {size2index,s2u}_compute().

This {bug,regression} was introduced by
155bfa7da1 (Normalize size classes.).

This resolves #241.
This commit is contained in:
Jason Evans 2015-07-09 21:36:33 -07:00
parent 7ae1239177
commit dde067264d
3 changed files with 96 additions and 2 deletions

View File

@ -139,6 +139,7 @@ TESTS_UNIT := $(srcroot)test/unit/atomic.c \
$(srcroot)test/unit/rb.c \
$(srcroot)test/unit/rtree.c \
$(srcroot)test/unit/SFMT.c \
$(srcroot)test/unit/size_classes.c \
$(srcroot)test/unit/stats.c \
$(srcroot)test/unit/tsd.c \
$(srcroot)test/unit/util.c \

View File

@ -528,7 +528,9 @@ size2index_compute(size_t size)
}
#endif
{
size_t x = lg_floor((size<<1)-1);
size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
(ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
: lg_floor((size<<1)-1);
size_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
size_t grp = shift << LG_SIZE_CLASS_GROUP;
@ -624,7 +626,9 @@ s2u_compute(size_t size)
}
#endif
{
size_t x = lg_floor((size<<1)-1);
size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
(ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
: lg_floor((size<<1)-1);
size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
size_t delta = ZU(1) << lg_delta;

89
test/unit/size_classes.c Normal file
View File

@ -0,0 +1,89 @@
#include "test/jemalloc_test.h"
static size_t
get_max_size_class(void)
{
unsigned nhchunks;
size_t mib[4];
size_t sz, miblen, max_size_class;
sz = sizeof(unsigned);
assert_d_eq(mallctl("arenas.nhchunks", &nhchunks, &sz, NULL, 0), 0,
"Unexpected mallctl() error");
miblen = sizeof(mib) / sizeof(size_t);
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
"Unexpected mallctlnametomib() error");
mib[2] = nhchunks - 1;
sz = sizeof(size_t);
assert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,
"Unexpected mallctlbymib() error");
return (max_size_class);
}
TEST_BEGIN(test_size_classes)
{
size_t size_class, max_size_class;
index_t index, max_index;
max_size_class = get_max_size_class();
max_index = size2index(max_size_class);
for (index = 0, size_class = index2size(index); index < max_index ||
size_class < max_size_class; index++, size_class =
index2size(index)) {
assert_true(index < max_index,
"Loop conditionals should be equivalent; index=%u, "
"size_class=%zu (%#zx)", index, size_class, size_class);
assert_true(size_class < max_size_class,
"Loop conditionals should be equivalent; index=%u, "
"size_class=%zu (%#zx)", index, size_class, size_class);
assert_u_eq(index, size2index(size_class),
"size2index() does not reverse index2size(): index=%u -->"
" size_class=%zu --> index=%u --> size_class=%zu", index,
size_class, size2index(size_class),
index2size(size2index(size_class)));
assert_zu_eq(size_class, index2size(size2index(size_class)),
"index2size() does not reverse size2index(): index=%u -->"
" size_class=%zu --> index=%u --> size_class=%zu", index,
size_class, size2index(size_class),
index2size(size2index(size_class)));
assert_u_eq(index+1, size2index(size_class+1),
"Next size_class does not round up properly");
assert_zu_eq(size_class, (index > 0) ?
s2u(index2size(index-1)+1) : s2u(1),
"s2u() does not round up to size class");
assert_zu_eq(size_class, s2u(size_class-1),
"s2u() does not round up to size class");
assert_zu_eq(size_class, s2u(size_class),
"s2u() does not compute same size class");
assert_zu_eq(s2u(size_class+1), index2size(index+1),
"s2u() does not round up to next size class");
}
assert_u_eq(index, size2index(index2size(index)),
"size2index() does not reverse index2size()");
assert_zu_eq(max_size_class, index2size(size2index(max_size_class)),
"index2size() does not reverse size2index()");
assert_zu_eq(size_class, s2u(index2size(index-1)+1),
"s2u() does not round up to size class");
assert_zu_eq(size_class, s2u(size_class-1),
"s2u() does not round up to size class");
assert_zu_eq(size_class, s2u(size_class),
"s2u() does not compute same size class");
}
TEST_END
int
main(void)
{
return (test(
test_size_classes));
}