[commit: ghc] master: Make integer overflow less likely to happen (#7762) (36b042f)
git at git.haskell.org
git at git.haskell.org
Fri Oct 25 11:19:14 UTC 2013
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/36b042fbf60210ab6859d96e5b4b5e121085816d/ghc
>---------------------------------------------------------------
commit 36b042fbf60210ab6859d96e5b4b5e121085816d
Author: Simon Marlow <marlowsd at gmail.com>
Date: Fri Oct 25 10:40:23 2013 +0100
Make integer overflow less likely to happen (#7762)
The particular problematic code in #7762 was this:
nat newSize = size - n;
char *freeAddr = MBLOCK_ROUND_DOWN(bd->start);
freeAddr += newSize * MBLOCK_SIZE;
^^^^^^^^^^^^^^^^^^^^^^ OVERFLOW!!!
For good measure, I'm going to fix the bug twice. This patch fixes
the class of bugs of this kind, by making sure that any expressions
involving BLOCK_SIZE or MBLOCK_SIZE are promoted to unsigned long. In
a separate patch, I'll fix a bunch of individual instances (including
the one above).
>---------------------------------------------------------------
36b042fbf60210ab6859d96e5b4b5e121085816d
includes/rts/storage/Block.h | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/includes/rts/storage/Block.h b/includes/rts/storage/Block.h
index 008602a..7b3bc99 100644
--- a/includes/rts/storage/Block.h
+++ b/includes/rts/storage/Block.h
@@ -15,7 +15,13 @@
/* Block related constants (BLOCK_SHIFT is defined in Constants.h) */
+#ifdef CMINUSMINUS
#define BLOCK_SIZE (1<<BLOCK_SHIFT)
+#else
+#define BLOCK_SIZE (1UL<<BLOCK_SHIFT)
+// Note [integer overflow]
+#endif
+
#define BLOCK_SIZE_W (BLOCK_SIZE/sizeof(W_))
#define BLOCK_MASK (BLOCK_SIZE-1)
@@ -24,7 +30,13 @@
/* Megablock related constants (MBLOCK_SHIFT is defined in Constants.h) */
+#ifdef CMINUSMINUS
#define MBLOCK_SIZE (1<<MBLOCK_SHIFT)
+#else
+#define MBLOCK_SIZE (1UL<<MBLOCK_SHIFT)
+// Note [integer overflow]
+#endif
+
#define MBLOCK_SIZE_W (MBLOCK_SIZE/sizeof(W_))
#define MBLOCK_MASK (MBLOCK_SIZE-1)
@@ -37,6 +49,18 @@
*/
#define LARGE_OBJECT_THRESHOLD ((nat)(BLOCK_SIZE * 8 / 10))
+/*
+ * Note [integer overflow]
+ *
+ * The UL suffix in BLOCK_SIZE and MBLOCK_SIZE promotes the expression
+ * to an unsigned long, which means that expressions involving these
+ * will be promoted to unsigned long, which makes integer overflow
+ * less likely. Historically, integer overflow in expressions like
+ * (n * BLOCK_SIZE)
+ * where n is int or unsigned int, have caused obscure segfaults in
+ * programs that use large amounts of memory (e.g. #7762, #5086).
+ */
+
/* -----------------------------------------------------------------------------
* Block descriptor. This structure *must* be the right length, so we
* can do pointer arithmetic on pointers to it.
More information about the ghc-commits
mailing list