aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-11-09 12:08:28 -0500
committerNick Mathewson <nickm@torproject.org>2011-11-09 14:48:52 -0500
commite1c6431e42bc6b5619c78008cbe92730ead57bbf (patch)
tree0be531fd05c9c884add652ca81427b3a9a48705f /src
parentbe6928d6e78a47800a96962403efff753ad70e84 (diff)
downloadtor-e1c6431e42bc6b5619c78008cbe92730ead57bbf.tar
tor-e1c6431e42bc6b5619c78008cbe92730ead57bbf.tar.gz
Correct the handling of overflow behavior in smartlist_ensure_capacity
The old behavior was susceptible to the compiler optimizing out our assertion check, *and* could still overflow size_t on 32-bit systems even when it did work.
Diffstat (limited to 'src')
-rw-r--r--src/common/container.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/common/container.c b/src/common/container.c
index c741eb020..edfcd973f 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -61,13 +61,22 @@ smartlist_clear(smartlist_t *sl)
static INLINE void
smartlist_ensure_capacity(smartlist_t *sl, int size)
{
+#if SIZEOF_SIZE_T > SIZEOF_INT
+#define MAX_CAPACITY (INT_MAX)
+#else
+#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*))))
+#endif
if (size > sl->capacity) {
- int higher = sl->capacity * 2;
- while (size > higher)
- higher *= 2;
- tor_assert(higher > 0); /* detect overflow */
+ int higher = sl->capacity;
+ if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) {
+ tor_assert(size <= MAX_CAPACITY);
+ higher = MAX_CAPACITY;
+ } else {
+ while (size > higher)
+ higher *= 2;
+ }
sl->capacity = higher;
- sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
+ sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity));
}
}