diff --git a/glib/glib.symbols b/glib/glib.symbols
index ad2b509..afdb39f 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -720,13 +720,19 @@ g_markup_collect_attributes
 g_free
 g_malloc G_GNUC_MALLOC
 g_malloc0 G_GNUC_MALLOC
+g_malloc_n G_GNUC_MALLOC
+g_malloc0_n G_GNUC_MALLOC
 g_mem_is_system_malloc
 g_mem_profile
 g_mem_set_vtable
 g_realloc
+g_realloc_n
 g_try_malloc G_GNUC_MALLOC
 g_try_malloc0 G_GNUC_MALLOC
+g_try_malloc_n G_GNUC_MALLOC
+g_try_malloc0_n G_GNUC_MALLOC
 g_try_realloc
+g_try_realloc_n
 #ifndef G_DISABLE_DEPRECATED
 g_allocator_free
 g_allocator_new
diff --git a/glib/gmem.c b/glib/gmem.c
index b9ce0a6..b52a6ec 100644
--- a/glib/gmem.c
+++ b/glib/gmem.c
@@ -203,11 +203,11 @@ g_try_malloc (gsize n_bytes)
 
 gpointer
 g_try_malloc0 (gsize n_bytes)
-{ 
+{
   gpointer mem;
 
   mem = g_try_malloc (n_bytes);
-  
+
   if (mem)
     memset (mem, 0, n_bytes);
 
@@ -229,6 +229,91 @@ g_try_realloc (gpointer mem,
   return NULL;
 }
 
+
+#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((a) > G_MAXSIZE / (b)))
+
+gpointer
+g_malloc_n (gsize n_blocks,
+	    gsize n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    {
+      if (G_UNLIKELY (!g_mem_initialized))
+	g_mem_init_nomessage();
+
+      g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
+               G_STRLOC, n_blocks, n_block_bytes);
+    }
+
+  return g_malloc (n_blocks * n_block_bytes);
+}
+
+gpointer
+g_malloc0_n (gsize n_blocks,
+	     gsize n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    {
+      if (G_UNLIKELY (!g_mem_initialized))
+	g_mem_init_nomessage();
+
+      g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
+               G_STRLOC, n_blocks, n_block_bytes);
+    }
+
+  return g_malloc0 (n_blocks * n_block_bytes);
+}
+
+gpointer
+g_realloc_n (gpointer mem,
+	     gsize    n_blocks,
+	     gsize    n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    {
+      if (G_UNLIKELY (!g_mem_initialized))
+	g_mem_init_nomessage();
+
+      g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
+               G_STRLOC, n_blocks, n_block_bytes);
+    }
+
+  return g_realloc (mem, n_blocks * n_block_bytes);
+}
+
+gpointer
+g_try_malloc_n (gsize n_blocks,
+		gsize n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    return NULL;
+
+  return g_try_malloc (n_blocks * n_block_bytes);
+}
+
+gpointer
+g_try_malloc0_n (gsize n_blocks,
+		 gsize n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    return NULL;
+
+  return g_try_malloc0 (n_blocks * n_block_bytes);
+}
+
+gpointer
+g_try_realloc_n (gpointer mem,
+		 gsize    n_blocks,
+		 gsize    n_block_bytes)
+{
+  if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
+    return NULL;
+
+  return g_try_realloc (mem, n_blocks * n_block_bytes);
+}
+
+
+
 static gpointer
 fallback_calloc (gsize n_blocks,
 		 gsize n_block_bytes)
diff --git a/glib/gmem.h b/glib/gmem.h
index 8cb050e..4c805d4 100644
--- a/glib/gmem.h
+++ b/glib/gmem.h
@@ -48,40 +48,88 @@ typedef struct _GMemVTable GMemVTable;
 
 /* Memory allocation functions
  */
+
+void	 g_free	          (gpointer	 mem);
+
 gpointer g_malloc         (gsize	 n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
 gpointer g_malloc0        (gsize	 n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
 gpointer g_realloc        (gpointer	 mem,
 			   gsize	 n_bytes) G_GNUC_WARN_UNUSED_RESULT;
-void	 g_free	          (gpointer	 mem);
 gpointer g_try_malloc     (gsize	 n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
 gpointer g_try_malloc0    (gsize	 n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
 gpointer g_try_realloc    (gpointer	 mem,
 			   gsize	 n_bytes) G_GNUC_WARN_UNUSED_RESULT;
 
+gpointer g_malloc_n       (gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
+gpointer g_malloc0_n      (gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
+gpointer g_realloc_n      (gpointer	 mem,
+			   gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
+gpointer g_try_malloc_n   (gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
+gpointer g_try_malloc0_n  (gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
+gpointer g_try_realloc_n  (gpointer	 mem,
+			   gsize	 n_blocks,
+			   gsize	 n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
+
 
 /* Convenience memory allocators
  */
-#define g_new(struct_type, n_structs)		\
-    ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define g_new0(struct_type, n_structs)		\
-    ((struct_type *) g_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define g_renew(struct_type, mem, n_structs)	\
-    ((struct_type *) g_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
 
-#define g_try_new(struct_type, n_structs)		\
-    ((struct_type *) g_try_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define g_try_new0(struct_type, n_structs)		\
-    ((struct_type *) g_try_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define g_try_renew(struct_type, mem, n_structs)	\
-    ((struct_type *) g_try_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
+
+  /* avoid the overflow check for the common case of n_blocks or n_block_bytes being 1 */
+#  define _G_MALLOC_N(n_blocks, n_block_bytes, func_1, func_n) \
+       (__extension__						\
+	({ \
+	   register gsize __n = (gsize) (n_blocks);		\
+	   gpointer __p;					\
+	   if (__builtin_constant_p (__n) && __n == 1)		\
+	     __p = func_1 (n_block_bytes);			\
+	   else							\
+	     __p = func_n (n_blocks, n_block_bytes);		\
+	  __p; }))
+#  define _G_REALLOC_N(mem, n_blocks, n_block_bytes, func_1, func_n) \
+       (__extension__						\
+	({ \
+	   register gsize __n = (gsize) (n_blocks);		\
+	   gpointer __p;					\
+	   if (__builtin_constant_p (__n) && __n == 1)		\
+	     __p = func_1 ((mem), n_block_bytes);		\
+	   else							\
+	     __p = func_n ((mem), n_blocks, n_block_bytes);	\
+	  __p; }))
+
+#else /* fallback implementation */
+#  define _G_MALLOC_N(n_blocks, n_block_bytes, func_1, func_n) \
+	  (func_n (n_blocks, n_block_bytes))
+#  define _G_REALLOC_N(mem, n_blocks, n_block_bytes, func_1, func_n) \
+	  (func_n (mem, n_blocks, n_block_bytes))
+#endif
+
+
+#define _G_NEW(struct_type, n_structs, func_1, func_n)	\
+	((struct_type *) _G_MALLOC_N ((n_structs), sizeof (struct_type), func_1, func_n))
+#  define _G_RENEW(struct_type, mem, n_structs, func_1, func_n)	\
+	((struct_type *) _G_REALLOC_N ((mem), (n_structs), sizeof (struct_type), func_1, func_n))
+
+#define g_new(struct_type, n_structs)		_G_NEW (struct_type, n_structs, g_malloc, g_malloc_n)
+#define g_new0(struct_type, n_structs)		_G_NEW (struct_type, n_structs, g_malloc0, g_malloc0_n)
+#define g_renew(struct_type, mem, n_structs)	_G_RENEW (struct_type, mem, n_structs, g_realloc, g_realloc_n)
+
+#define g_try_new(struct_type, n_structs)	_G_NEW (struct_type, n_structs, g_try_malloc, g_try_malloc_n)
+#define g_try_new0(struct_type, n_structs)	_G_NEW (struct_type, n_structs, g_try_malloc0, g_try_malloc0_n)
+#define g_try_renew(struct_type, mem,n_structs)	_G_RENEW (struct_type, mem, n_structs, g_try_realloc, g_try_realloc_n)
 
 
 /* Memory allocation virtualization for debugging purposes
  * g_mem_set_vtable() has to be the very first GLib function called
  * if being used
  */
-struct _GMemVTable
-{
+struct _GMemVTable {
   gpointer (*malloc)      (gsize    n_bytes);
   gpointer (*realloc)     (gpointer mem,
 			   gsize    n_bytes);
