On Thu, Jul 10, 2014 at 02:42:34PM -0400, Ted Unangst wrote:
> On Thu, Jul 10, 2014 at 10:28, Matthew Dempsky wrote:
> > We've found a bunch of uses for reallocarray() in userland, and I
> > think the idiom is worth reusing in the kernel.  There are enough
> > places where we do malloc(x * y) that I think it makes sense to add
> > mallocarray(x, y).
> 
> > +void       *malloc(unsigned long size, int type, int flags);
> > +void       *mallocarray(unsigned long nmemb, unsigned long size,
> > +       int type, int flags);
> 
> The unsigned long here is ancient history. It should be size_t I think.
> 
> > Index: sys/kern/kern_mallocarray.c
> 
> Please just add it to kern_malloc.c without creating a new file.

ok?

Index: share/man/man9/Makefile
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/share/man/man9/Makefile,v
retrieving revision 1.210
diff -u -p -r1.210 Makefile
--- share/man/man9/Makefile     30 Jun 2014 21:48:09 -0000      1.210
+++ share/man/man9/Makefile     10 Jul 2014 17:15:45 -0000
@@ -232,7 +232,7 @@ MLINKS+=ktrace.9 ktrcsw.9 ktrace.9 ktrem
        ktrace.9 ktrsysret.9 ktrace.9 KTRPOINT.9
 MLINKS+=lock.9 lockinit.9 lock.9 lockmgr.9 lock.9 lockstatus.9
 MLINKS+=log.9 addlog.9
-MLINKS+=malloc.9 free.9
+MLINKS+=malloc.9 mallocarray.9 malloc.9 free.9
 MLINKS+=membar_sync.9 membar_enter.9 membar_sync.9 membar_exit.9 \
        membar_sync.9 membar_producer.9 membar_sync.9 membar_consumer.9
 MLINKS+=mbuf.9 m_copym2.9 mbuf.9 m_copym.9 mbuf.9 m_free.9 mbuf.9 MFREE.9 \
Index: share/man/man9/malloc.9
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/share/man/man9/malloc.9,v
retrieving revision 1.52
diff -u -p -r1.52 malloc.9
--- share/man/man9/malloc.9     3 Apr 2014 04:10:34 -0000       1.52
+++ share/man/man9/malloc.9     10 Jul 2014 18:52:54 -0000
@@ -33,13 +33,16 @@
 .Os
 .Sh NAME
 .Nm malloc ,
+.Nm mallocarray ,
 .Nm free
 .Nd kernel memory allocator
 .Sh SYNOPSIS
 .In sys/types.h
 .In sys/malloc.h
 .Ft void *
-.Fn malloc "unsigned long size" "int type" "int flags"
+.Fn malloc "size_t size" "int type" "int flags"
+.Ft void *
+.Fn malloc "size_t nmemb" "size_t size" "int type" "int flags"
 .Ft void
 .Fn free "void *addr" "int type"
 .Sh DESCRIPTION
@@ -48,8 +51,17 @@ The
 function allocates uninitialized memory in kernel address space for an
 object whose size is specified by
 .Fa size .
+The
+.Fn mallocarray
+function is the same as
+.Fn malloc ,
+except it allocates space for an array of
+.Fa nmemb
+objects and checks for arithmetic overflow.
+.Pp
+The
 .Fn free
-releases memory at address
+function releases memory at address
 .Fa addr
 that was previously allocated by
 .Fn malloc
@@ -60,7 +72,8 @@ is a null pointer, no action occurs.
 .Pp
 The
 .Fa flags
-argument further qualifies malloc's
+argument further qualifies
+.Fn malloc Ns 's
 operational characteristics as follows:
 .Bl -tag -width xxx -offset indent
 .It Dv M_WAITOK
Index: sys/sys/malloc.h
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/sys/malloc.h,v
retrieving revision 1.108
diff -u -p -r1.108 malloc.h
--- sys/sys/malloc.h    19 May 2014 14:30:03 -0000      1.108
+++ sys/sys/malloc.h    10 Jul 2014 18:49:44 -0000
@@ -391,10 +391,11 @@ extern struct kmemusage *kmemusage;
 extern char *kmembase;
 extern struct kmembuckets bucket[];
 
-extern void *malloc(unsigned long size, int type, int flags);
-extern void free(void *addr, int type);
-extern int sysctl_malloc(int *, u_int, void *, size_t *, void *, size_t,
-                             struct proc *);
+void   *malloc(size_t, int, int);
+void   *mallocarray(size_t, size_t, int, int);
+void   free(void *, int);
+int    sysctl_malloc(int *, u_int, void *, size_t *, void *, size_t,
+           struct proc *);
 
 size_t malloc_roundup(size_t);
 void   malloc_printit(int (*)(const char *, ...));
Index: sys/kern/kern_malloc.c
===================================================================
RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.107
diff -u -p -r1.107 kern_malloc.c
--- sys/kern/kern_malloc.c      19 May 2014 14:30:03 -0000      1.107
+++ sys/kern/kern_malloc.c      10 Jul 2014 18:50:15 -0000
@@ -159,7 +159,7 @@ struct timeval malloc_lasterr;
  * Allocate a block of memory
  */
 void *
-malloc(unsigned long size, int type, int flags)
+malloc(size_t size, int type, int flags)
 {
        struct kmembuckets *kbp;
        struct kmemusage *kup;
@@ -701,3 +701,37 @@ malloc_printit(
 #endif
 }
 #endif /* DDB */
+
+/*
+ * Copyright (c) 2008 Otto Moerbeek <o...@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW        (1UL << (sizeof(size_t) * 4))
+
+void *
+mallocarray(size_t nmemb, size_t size, int type, int flags)
+{
+       if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+           nmemb > 0 && SIZE_MAX / nmemb < size) {
+               if (flags & M_CANFAIL)
+                       return (NULL);
+               panic("overflow");
+       }
+       return (malloc(size * nmemb, type, flags));
+}

Reply via email to