aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-09-13 10:34:49 -0400
committerNick Mathewson <nickm@torproject.org>2012-09-14 09:51:24 -0400
commit37953497d8689bdde65837b00f56bf8ff1e0e459 (patch)
treeeba5ce37971b301dffc9fe788b2ab1d439717284 /src/common
parent582f2187a769ea723f6bf13bc91f7a4b3c861408 (diff)
downloadtor-37953497d8689bdde65837b00f56bf8ff1e0e459.tar
tor-37953497d8689bdde65837b00f56bf8ff1e0e459.tar.gz
Don't compute ((uint64_t)1)<<64 in round_to_power_of_2
This would be undefined behavior if it happened. (It can't actually happen as we're using round_to_power_of_2, since we would have to be trying to allocate exabytes of data.) While we're at it, fix the behavior of round_to_power_of_2(0), and document the function better. Fix for bug 6831.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/util.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/common/util.c b/src/common/util.c
index 84b31502e..0e0dcb179 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -394,12 +394,24 @@ tor_log2(uint64_t u64)
return r;
}
-/** Return the power of 2 closest to <b>u64</b>. */
+/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If
+ * there are two powers of 2 equally close, round down. */
uint64_t
round_to_power_of_2(uint64_t u64)
{
- int lg2 = tor_log2(u64);
- uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1);
+ int lg2;
+ uint64_t low;
+ uint64_t high;
+ if (u64 == 0)
+ return 1;
+
+ lg2 = tor_log2(u64);
+ low = U64_LITERAL(1) << lg2;
+
+ if (lg2 == 63)
+ return low;
+
+ high = U64_LITERAL(1) << (lg2+1);
if (high - u64 < u64 - low)
return high;
else