diff --git a/configure.ac b/configure.ac index 2248380ca96eaf8c134c4c053b6f0a64b7afe3e1..133ee27746fdce441087133560090e968f949956 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,7 @@ XTRANS_CONNECTION_FLAGS # Checks for library functions. AC_CHECK_FUNCS([strlcpy strnlen]) +AC_REPLACE_FUNCS([reallocarray]) # Allow checking code with lint, sparse, etc. XORG_WITH_LINT diff --git a/src/FSFontInfo.c b/src/FSFontInfo.c index fd807ae46c71ea8dbc7c1db47eed96c6e0676c7a..3a5fe4309fd5ff39ca50cb6f8d409ccc5ad21c58 100644 --- a/src/FSFontInfo.c +++ b/src/FSFontInfo.c @@ -130,7 +130,7 @@ FSListFontsWithXInfo( if (fhdr) { #define ResizeArray(var, type) { \ - type **tmp = FSrealloc(var, sizeof(type *) * size); \ + type **tmp = FSreallocarray(var, size, sizeof(type *)); \ if (tmp) \ var = tmp; \ else \ @@ -144,7 +144,7 @@ FSListFontsWithXInfo( ResizeArray(pd, unsigned char) } else { #define InitArray(var, type) \ - if ((var = FSmalloc(sizeof(type *) * size)) == NULL) { \ + if ((var = FSmallocarray(size, sizeof(type *))) == NULL) { \ goto badmem; \ } @@ -184,7 +184,7 @@ FSListFontsWithXInfo( goto cleanpi; #endif - po[i] = FSmalloc(pi[i]->num_offsets * sizeof(FSPropOffset)); + po[i] = FSmallocarray(pi[i]->num_offsets, sizeof(FSPropOffset)); if (!po[i]) goto cleanpi; pd[i] = FSmalloc(pi[i]->data_len); diff --git a/src/FSFtNames.c b/src/FSFtNames.c index 1dea246a505155c8fd232c8efc3765d6128b1397..23c93a3dbd80bcffb44404f1e2f15c85526ef3e5 100644 --- a/src/FSFtNames.c +++ b/src/FSFtNames.c @@ -98,7 +98,7 @@ FSListFonts( && rep.length <= (SIZE_MAX >> 2) #endif ) { - flist = FSmalloc(rep.nFonts * sizeof(char *)); + flist = FSmallocarray(rep.nFonts, sizeof(char *)); rlen = (rep.length << 2) - SIZEOF(fsListFontsReply); c = FSmalloc(rlen + 1); diff --git a/src/FSGetCats.c b/src/FSGetCats.c index d8fae40fb432cb603a61570e9d5a97dce735d604..4c27a343f75b102b6b686529813f96d95155dac2 100644 --- a/src/FSGetCats.c +++ b/src/FSGetCats.c @@ -79,7 +79,7 @@ FSGetCatalogues( && rep.length <= (SIZE_MAX >> 2) #endif ) { - list = FSmalloc(rep.num_catalogues * sizeof(char *)); + list = FSmallocarray(rep.num_catalogues, sizeof(char *)); rlen = (rep.length << 2) - SIZEOF(fsGetCataloguesReply); c = FSmalloc(rlen + 1); if ((!list) || (!c)) { diff --git a/src/FSListCats.c b/src/FSListCats.c index 2bc139394dbaad4033bf77fb12fff79426cee57d..9fb380c7b5cb5744afc11e5b865d105ffdd7de49 100644 --- a/src/FSListCats.c +++ b/src/FSListCats.c @@ -97,7 +97,7 @@ FSListCatalogues( && rep.length <= (SIZE_MAX>>2) #endif ) { - clist = FSmalloc(rep.num_catalogues * sizeof(char *)); + clist = FSmallocarray(rep.num_catalogues, sizeof(char *)); rlen = (rep.length << 2) - SIZEOF(fsListCataloguesReply); c = FSmalloc(rlen + 1); diff --git a/src/FSListExt.c b/src/FSListExt.c index 8d83bd3cd1f06745c408712cd6f44e5197ab3053..a4249f42e1cefd533390f0f6ec2a078e19033185 100644 --- a/src/FSListExt.c +++ b/src/FSListExt.c @@ -79,7 +79,7 @@ FSListExtensions( && rep.length <= (SIZE_MAX>>2) #endif ) { - list = FSmalloc(rep.nExtensions * sizeof(char *)); + list = FSmallocarray(rep.nExtensions, sizeof(char *)); rlen = (rep.length << 2) - SIZEOF(fsListExtensionsReply); c = FSmalloc(rlen + 1); if ((!list) || (!c)) { diff --git a/src/FSOpenServ.c b/src/FSOpenServ.c index faebe1301408b97663f9241fbfd94264d4b50f6f..5acef9fc80ac2afda70becae6aec3162e37235e0 100644 --- a/src/FSOpenServ.c +++ b/src/FSOpenServ.c @@ -167,7 +167,7 @@ FSOpenServer(const char *server) } #endif - alts = FSmalloc(sizeof(AlternateServer) * prefix.num_alternates); + alts = FSmallocarray(prefix.num_alternates, sizeof(AlternateServer)); if (!alts) { goto fail; } diff --git a/src/FSQGlyphs.c b/src/FSQGlyphs.c index e40c88a934dbcafd83742aefa4f1a0680f002590..662da36b72cdf828719a8da20776d016fb963c36 100644 --- a/src/FSQGlyphs.c +++ b/src/FSQGlyphs.c @@ -93,7 +93,7 @@ FSQueryXBitmaps8( return FSBadAlloc; #endif - offs = FSmalloc(sizeof(FSOffset) * reply.num_chars); + offs = FSmallocarray(reply.num_chars, sizeof(FSOffset)); *offsets = offs; if (!offs) return FSBadAlloc; @@ -160,7 +160,7 @@ FSQueryXBitmaps16( if (str_len > SIZE_MAX/SIZEOF(fsChar2b_version1)) return FSBadAlloc; - swapped_str = FSmalloc(SIZEOF(fsChar2b_version1) * str_len); + swapped_str = FSmallocarray(str_len, SIZEOF(fsChar2b_version1)); if (!swapped_str) return FSBadAlloc; for (unsigned long i = 0; i < str_len; i++) { @@ -182,7 +182,7 @@ FSQueryXBitmaps16( if(reply.num_chars > SIZE_MAX/sizeof(FSOffset)) return FSBadAlloc; #endif - offs = FSmalloc(sizeof(FSOffset) * reply.num_chars); + offs = FSmallocarray(reply.num_chars, sizeof(FSOffset)); *offsets = offs; if (!offs) return FSBadAlloc; diff --git a/src/FSQXExt.c b/src/FSQXExt.c index 1469636d5c64cf27bf30202a16eb851fa52491ac..65f35b1c7ddc0b987899abe4bf9e9e6f8a45f402 100644 --- a/src/FSQXExt.c +++ b/src/FSQXExt.c @@ -100,7 +100,7 @@ FSQueryXExtents8( return FSBadAlloc; #endif - ext = FSmalloc(sizeof(FSXCharInfo) * reply.num_extents); + ext = FSmallocarray(reply.num_extents, sizeof(FSXCharInfo)); *extents = ext; if (!ext) return FSBadAlloc; @@ -141,7 +141,7 @@ FSQueryXExtents16( { fsChar2b_version1 *swapped_str; - swapped_str = FSmalloc(SIZEOF(fsChar2b_version1) * str_len); + swapped_str = FSmallocarray(str_len, SIZEOF(fsChar2b_version1)); if (!swapped_str) return FSBadAlloc; for (unsigned long i = 0; i < str_len; i++) { @@ -164,7 +164,7 @@ FSQueryXExtents16( return FSBadAlloc; #endif - ext = FSmalloc(sizeof(FSXCharInfo) * reply.num_extents); + ext = FSmallocarray(reply.num_extents, sizeof(FSXCharInfo)); *extents = ext; if (!ext) return FSBadAlloc; diff --git a/src/FSQXInfo.c b/src/FSQXInfo.c index de776ce2ae724e6d5dcb7080ff5736a2f9508e16..f497a094a8b7f96e5b9d801b2f7ca0a995c9d8df 100644 --- a/src/FSQXInfo.c +++ b/src/FSQXInfo.c @@ -97,7 +97,7 @@ FSQueryXInfo( #endif /* prepare for prop data */ - offset_data = FSmalloc(props->num_offsets * sizeof(FSPropOffset)); + offset_data = FSmallocarray(props->num_offsets, sizeof(FSPropOffset)); if (!offset_data) return FSBadAlloc; pdata = FSmalloc(props->data_len); diff --git a/src/FSlibos.h b/src/FSlibos.h index baf9902bcd90024bfa95cab267dc68fd42ff2b28..c09d36db2314f212703d5421b33e10ad468b01dd 100644 --- a/src/FSlibos.h +++ b/src/FSlibos.h @@ -54,6 +54,7 @@ in this Software without prior written authorization from The Open Group. */ #include +#include #include #ifndef WIN32 @@ -270,6 +271,11 @@ typedef fd_set FdSet; #define UnlockDisplay(dis) #define FSfree(ptr) free((ptr)) +#ifndef HAVE_REALLOCARRAY +extern _X_HIDDEN void *fsreallocarray(void *optr, size_t nmemb, size_t size); +# define reallocarray(ptr, n, size) \ + fsreallocarray((ptr), (size_t)(n), (size_t)(size)) +#endif /* * Note that some machines do not return a valid pointer for malloc(0), in @@ -278,16 +284,22 @@ typedef fd_set FdSet; * FSlib code expects malloc(0) to return a valid pointer to storage. */ -#ifdef MALLOC_0_RETURNS_NULL +#if defined(MALLOC_0_RETURNS_NULL) || defined(__clang_analyzer__) # define FSmalloc(size) malloc(((size) > 0 ? (size) : 1)) # define FSrealloc(ptr, size) realloc((ptr), ((size) > 0 ? (size) : 1)) # define FScalloc(nelem, elsize) calloc(((nelem) > 0 ? (nelem) : 1), (elsize)) +# define FSreallocarray(ptr, n, size) \ + reallocarray((ptr), ((n) == 0 ? 1 : (n)), size) #else # define FSmalloc(size) malloc((size)) # define FSrealloc(ptr, size) realloc((ptr), (size)) # define FScalloc(nelem, elsize) calloc((nelem), (elsize)) +# define FSreallocarray(ptr, n, size) reallocarray((ptr), (n), (size)) + #endif +#define FSmallocarray(n, size) FSreallocarray(NULL, (n), (size)) + #define SearchString(string, char) index((string), (char)) diff --git a/src/Makefile.am b/src/Makefile.am index 56fd0db34c6f2f575cebd9f3e6e8a8ee8e41c2bb..327be0a8b88c0a0b98a897f2d4bc7b38bf9338bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,7 +38,7 @@ AM_CFLAGS = \ AM_CPPFLAGS = -I$(top_srcdir)/include/X11/fonts -libFS_la_LIBADD = $(FS_LIBS) +libFS_la_LIBADD = $(LTLIBOBJS) $(FS_LIBS) libFS_la_LDFLAGS = -export-symbols-regex '^FS.*' -version-number 6:0:0 -no-undefined diff --git a/src/reallocarray.c b/src/reallocarray.c new file mode 100644 index 0000000000000000000000000000000000000000..aef38430211c5156b4c34f154a47f20a0ceea20b --- /dev/null +++ b/src/reallocarray.c @@ -0,0 +1,43 @@ +/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "FSlibos.h" + +/* + * 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 ((size_t)1 << (sizeof(size_t) * 4)) + +void * +fsreallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +}