]> granicus.if.org Git - check/commitdiff
Allow dynamic configuration of maximal assertion message size.
authorOren Ben-Kiki <oren@ben-kiki.org>
Sun, 27 Aug 2017 05:46:53 +0000 (08:46 +0300)
committerOren Ben-Kiki <oren@ben-kiki.org>
Sun, 27 Aug 2017 05:52:47 +0000 (08:52 +0300)
src/check.h.in
src/check_pack.c

index 76f09b0f2ff14fe248afb2a355c15943461279e6..46e9c4b4daeebf0113670710b18e94a567e0a62c 100644 (file)
@@ -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
index 5c03819be80bfb5919554da06e39cd19145a5ce1..88a1050e9b6cc6afc8ba8002d5c317d03a2487bd 100644 (file)
 #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)