Module Name: src Committed By: roy Date: Tue Apr 5 15:01:26 UTC 2016
Modified Files: src/lib/libc/stdlib: reallocarray.c Log Message: Stop calling reallocarr and just do the same bounds checking but without messing around with copying pointers which was causing ssh to crash. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/lib/libc/stdlib/reallocarray.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/stdlib/reallocarray.c diff -u src/lib/libc/stdlib/reallocarray.c:1.5 src/lib/libc/stdlib/reallocarray.c:1.6 --- src/lib/libc/stdlib/reallocarray.c:1.5 Sun Jul 26 02:22:33 2015 +++ src/lib/libc/stdlib/reallocarray.c Tue Apr 5 15:01:26 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: reallocarray.c,v 1.5 2015/07/26 02:22:33 kamil Exp $ */ +/* $NetBSD: reallocarray.c,v 1.6 2016/04/05 15:01:26 roy Exp $ */ /* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */ /*- @@ -31,22 +31,29 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: reallocarray.c,v 1.5 2015/07/26 02:22:33 kamil Exp $"); +__RCSID("$NetBSD: reallocarray.c,v 1.6 2016/04/05 15:01:26 roy Exp $"); #define _OPENBSD_SOURCE #include <errno.h> +#include <limits.h> #include <stdlib.h> +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) void * reallocarray(void *optr, size_t nmemb, size_t size) { - if (nmemb == 0 || size == 0) - return realloc(optr, 0); - int e = reallocarr(&optr, nmemb, size); - - if (e == 0) - return optr; - errno = e; - return NULL; + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if (__predict_false((nmemb | size) >= SQRT_SIZE_MAX && + nmemb > SIZE_MAX / size)) + { + errno = EOVERFLOW; + return NULL; + } + return realloc(optr, nmemb * size); }