summary refs log tree commit diff
path: root/net
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-09-09 02:28:47 -0300
committerArnaldo Carvalho de Melo <acme@mandriva.com>2005-09-09 02:28:47 -0300
commit0ba7a3ba6608de6e0c0bfe3009a63d7e0b7ab0ce (patch)
treedb5b9c5a778e0cbc08bcbf7f5b25174499b13a1d /net
parente104411b82f5c4d19752c335492036abdbf5880d (diff)
downloadlinux-0ba7a3ba6608de6e0c0bfe3009a63d7e0b7ab0ce.tar.gz
[CCID3] Avoid unsigned integer overflows in usecs_div
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'net')
-rw-r--r--net/dccp/ccids/ccid3.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 7bf3b3a91e97..ae0500c79d07 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -43,12 +43,22 @@
 #include "ccid3.h"
 
 /*
- * Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
+ * Reason for maths here is to avoid 32 bit overflow when a is big.
+ * With this we get close to the limit.
  */
 static inline u32 usecs_div(const u32 a, const u32 b)
 {
-	const u32 tmp = a * (USEC_PER_SEC / 10);
-	return b > 20 ? tmp / (b / 10) : tmp;
+	const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
+			a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
+			a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
+			a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
+			a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
+			a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
+			a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
+			a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
+								 100000;
+	const u32 tmp = a * (USEC_PER_SEC / div);
+	return (b >= 2 * div) ? tmp / (b / div) : tmp;
 }
 
 static int ccid3_debug;