From: Oren Ben-Kiki Date: Sun, 27 Aug 2017 05:46:53 +0000 (+0300) Subject: Allow dynamic configuration of maximal assertion message size. X-Git-Tag: 0.12.0~3^2~9 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cffe75c2865fa9c3337aa9c8ca8f56fb24f32918;p=check Allow dynamic configuration of maximal assertion message size. --- diff --git a/src/check.h.in b/src/check.h.in index 76f09b0..46e9c4b 100644 --- a/src/check.h.in +++ b/src/check.h.in @@ -2264,6 +2264,26 @@ CK_DLL_EXP pid_t CK_EXPORT check_fork(void); */ CK_DLL_EXP void CK_EXPORT check_waitpid_and_exit(pid_t pid) CK_ATTRIBUTE_NORETURN; +/** + * Set the maximal assertion message size. + * + * This protects the code against unintentional extremely large assertion messages + * (values of up to 4GB were seen in the wild). + * The usual size for a message is less than 80 bytes. + * + * By default, an assertion message is restricted to 4K bytes. + * It is possible to override this by setting the CK_MAX_MSG_SIZE environment variable, + * or by invoking this function. + * Specifying a non-positive argument resets the value, + * to the value specified by the environment variable, + * or to the default 4K bytes if the environment variable is not specified. + * + * @param max_msg_size the maximal assertion message size. + * + * @since 0.12.0 + */ +CK_DLL_EXP void CK_EXPORT check_set_max_msg_size(int max_msg_size); + #ifdef __cplusplus CK_CPPEND #endif diff --git a/src/check_pack.c b/src/check_pack.c index 5c03819..88a1050 100644 --- a/src/check_pack.c +++ b/src/check_pack.c @@ -38,16 +38,33 @@ #endif /* Maximum size for one message in the message stream. */ -#define CK_MAX_MSG_SIZE 8192 +static int ck_max_msg_size = 0; /* This is used to implement a sliding window on the receiving * side. When sending messages, we assure that no single message - * is bigger than this (actually we check against CK_MAX_MSG_SIZE/2). + * is bigger than this. * The usual size for a message is less than 80 bytes. * All this is done instead of the previous approach to allocate (actually * continuously reallocate) one big chunk for the whole message stream. * Problems were seen in the wild with up to 4 GB reallocations. */ +void check_set_max_msg_size(int max_msg_size) { + ck_max_msg_size = max_msg_size; +} + +static int get_max_msg_size(void) { + if (ck_max_msg_size <= 0) { + char *env = getenv("CK_MAX_MSG_SIZE"); + if (env) + ck_max_msg_size = atoi(env); + + if (ck_max_msg_size <= 0) + ck_max_msg_size = 4096; + } + return ck_max_msg_size; +} + + /* typedef an unsigned int that has at least 4 bytes */ typedef uint32_t ck_uint32; @@ -304,7 +321,7 @@ void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg) n = pack(type, &buf, msg); /* Keep it on the safe side to not send too much data. */ - if(n > (CK_MAX_MSG_SIZE / 2)) + if(n > get_max_msg_size()) eprintf("Message string too long", __FILE__, __LINE__ - 2); pthread_cleanup_push(ppack_cleanup, &ck_mutex_lock); @@ -455,9 +472,9 @@ RcvMsg *punpack(FILE * fdes) rmsg = rcvmsg_create(); /* Allcate a buffer */ - buf = (char *)emalloc(CK_MAX_MSG_SIZE); + buf = (char *)emalloc(get_max_msg_size() * 2); /* Fill the buffer from the file */ - nread = read_buf(fdes, CK_MAX_MSG_SIZE, buf); + nread = read_buf(fdes, get_max_msg_size() * 2, buf); nparse = nread; /* While not all parsed */ while(nparse > 0)