diff -Nru iperf3-3.0.7/debian/changelog iperf3-3.0.7/debian/changelog
--- iperf3-3.0.7/debian/changelog	2014-09-11 11:57:59.000000000 +0200
+++ iperf3-3.0.7/debian/changelog	2020-01-26 18:29:03.000000000 +0100
@@ -1,3 +1,9 @@
+iperf3 (3.0.7-1+deb8u1) jessie-security; urgency=high
+
+  * Integrate patch for CVE-2016-4303 (Closes: #827116)
+
+ -- Roberto Lumbreras <rover@debian.org>  Sun, 26 Jan 2020 18:29:03 +0100
+
 iperf3 (3.0.7-1) unstable; urgency=medium
 
   * new upstream version
diff -Nru iperf3-3.0.7/debian/control iperf3-3.0.7/debian/control
--- iperf3-3.0.7/debian/control	2014-06-20 14:53:09.000000000 +0200
+++ iperf3-3.0.7/debian/control	2020-01-26 18:13:23.000000000 +0100
@@ -1,8 +1,8 @@
 Source: iperf3
 Section: net
 Priority: optional
-Maintainer: Raoul Gunnar Borenius <borenius@dfn.de>
-Build-Depends: debhelper (>= 9), autotools-dev, uuid-dev
+Maintainer: Roberto Lumbreras <rover@debian.org>
+Build-Depends: debhelper (>= 9), autotools-dev, uuid-dev, dh-autoreconf
 Standards-Version: 3.9.5
 Homepage: http://software.es.net/iperf/
 
diff -Nru iperf3-3.0.7/debian/patches/002-CVE-2016-4303 iperf3-3.0.7/debian/patches/002-CVE-2016-4303
--- iperf3-3.0.7/debian/patches/002-CVE-2016-4303	1970-01-01 01:00:00.000000000 +0100
+++ iperf3-3.0.7/debian/patches/002-CVE-2016-4303	2020-01-26 17:57:39.000000000 +0100
@@ -0,0 +1,1973 @@
+From: "Bruce A. Mah" <bmah@es.net>
+Date: Fri, 3 Jun 2016 09:23:59 -0700
+Subject: [PATCH] Fix a buffer overflow / heap corruption issue that could
+ .
+ https://github.com/esnet/iperf/commit/f01a9ca8f7e878e438a53687dabe30b7f7222912
+ .
+ occur if a malformed JSON string was passed on the control channel.  This
+ issue, present in the cJSON library, was already fixed upstream, so was
+ addressed here in iperf3 by importing a newer version of cJSON (plus local
+ ESnet modifications).
+ .
+ Discovered and reported by Dave McDaniel, Cisco Talos.
+ .
+ Based on a patch by @dopheide-esnet, with input from @DaveGamble.
+ .
+ Cross-references:  TALOS-CAN-0164, ESNET-SECADV-2016-0001,
+ CVE-2016-4303
+ .
+ (cherry picked from commit ed94082be27d971a5e1b08b666e2c217cf470a40)
+ Signed-off-by: Bruce A. Mah <bmah@es.net>
+
+Index: iperf3-3.0.7/configure.ac
+===================================================================
+--- iperf3-3.0.7.orig/configure.ac	2020-01-26 16:42:51.505980684 +0100
++++ iperf3-3.0.7/configure.ac	2020-01-26 17:57:34.875507671 +0100
+@@ -7,7 +7,7 @@
+ 
+ 
+ # Initialize the automake system
+-AM_INIT_AUTOMAKE
++AM_INIT_AUTOMAKE([foreign])
+ 
+ AM_MAINTAINER_MODE
+ AM_CONFIG_HEADER(src/config.h)
+@@ -37,6 +37,12 @@
+ # Check for systems which need -lsocket and -lnsl
+ #AX_LIB_SOCKET_NSL
+ 
++# Check for the math library (needed by cjson on some platforms)
++AC_SEARCH_LIBS(floor, [m], [], [
++echo "floor()"
++exit 1
++])
++
+ # Solaris puts nanosleep in -lrt
+ AC_SEARCH_LIBS(nanosleep, [rt], [], [
+ echo "nanosleep() required for timing operations."
+Index: iperf3-3.0.7/src/cjson.c
+===================================================================
+--- iperf3-3.0.7.orig/src/cjson.c	2020-01-26 16:42:51.505980684 +0100
++++ iperf3-3.0.7/src/cjson.c	2020-01-26 17:11:58.755202470 +0100
+@@ -30,6 +30,9 @@
+ #include <float.h>
+ #include <limits.h>
+ #include <ctype.h>
++#ifdef HAVE_STDINT_H
++#include <stdint.h>
++#endif
+ #include <sys/types.h>
+ #include "cjson.h"
+ 
+@@ -39,994 +42,723 @@
+ #ifndef LLONG_MIN
+ #define LLONG_MIN (-LLONG_MAX - 1LL)
+ #endif
++static const char *global_ep;
+ 
++const char *cJSON_GetErrorPtr(void) {return global_ep;}
+ 
+-static const char *ep;
+-
+-const char *cJSON_GetErrorPtr( void )
+-{
+-	return ep;
+-}
+-
+-
+-static int cJSON_strcasecmp( const char *s1, const char *s2 )
++static int cJSON_strcasecmp(const char *s1,const char *s2)
+ {
+-	if ( ! s1 )
+-		return ( s1 == s2 ) ? 0 : 1;
+-	if ( ! s2 )
+-		return 1;
+-	for ( ; tolower(*s1) == tolower(*s2); ++s1, ++s2)
+-		if( *s1 == 0 )
+-			return 0;
++	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
++	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
+ 	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+ }
+ 
++static void *(*cJSON_malloc)(size_t sz) = malloc;
++static void (*cJSON_free)(void *ptr) = free;
+ 
+-static void *(*cJSON_malloc)( size_t ) = malloc;
+-static void (*cJSON_free)( void * ) = free;
+-
+-void cJSON_InitHooks(cJSON_Hooks* hooks)
++static char* cJSON_strdup(const char* str)
+ {
+-	if ( ! hooks ) {
+-		/* Reset hooks. */
+-		cJSON_malloc = malloc;
+-		cJSON_free = free;
+-		return;
+-	}
+-	cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
+-	cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
+-}
++      size_t len;
++      char* copy;
+ 
++      len = strlen(str) + 1;
++      if (!(copy = (char*)cJSON_malloc(len))) return 0;
++      memcpy(copy,str,len);
++      return copy;
++}
+ 
+-static char* cJSON_strdup( const char* str )
++void cJSON_InitHooks(cJSON_Hooks* hooks)
+ {
+-	size_t len;
+-	char* copy;
++    if (!hooks) { /* Reset hooks */
++        cJSON_malloc = malloc;
++        cJSON_free = free;
++        return;
++    }
+ 
+-	len = strlen( str ) + 1;
+-	if ( ! ( copy = (char*) cJSON_malloc( len ) ) )
+-		return 0;
+-	memcpy( copy, str, len );
+-	return copy;
++	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
++	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
+ }
+ 
+-
+ /* Internal constructor. */
+-static cJSON *cJSON_New_Item( void )
++static cJSON *cJSON_New_Item(void)
+ {
+-	cJSON* node = (cJSON*) cJSON_malloc( sizeof(cJSON) );
+-	if ( node )
+-		memset( node, 0, sizeof(cJSON) );
++	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
++	if (node) memset(node,0,sizeof(cJSON));
+ 	return node;
+ }
+ 
+-
+ /* Delete a cJSON structure. */
+-void cJSON_Delete( cJSON *c )
++void cJSON_Delete(cJSON *c)
+ {
+ 	cJSON *next;
+-
+-	while ( c ) {
+-		next = c->next;
+-		if ( ! ( c->type & cJSON_IsReference ) && c->child )
+-			cJSON_Delete( c->child );
+-		if ( ! ( c->type & cJSON_IsReference ) && c->valuestring )
+-			cJSON_free( c->valuestring );
+-		if ( c->string )
+-			cJSON_free( c->string );
+-		cJSON_free( c );
+-		c = next;
++	while (c)
++	{
++		next=c->next;
++		if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
++		if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
++		if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
++		cJSON_free(c);
++		c=next;
+ 	}
+ }
+ 
++/* Parse the input text to generate a number, and populate the result into item. */
++static const char *parse_number(cJSON *item,const char *num)
++{
++	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
+ 
+-static double ipow( double n, int exp )
+-{
+-	double r;
+-
+-	if ( exp < 0 )
+-		return 1.0 / ipow( n, -exp );
+-	r = 1;
+-	while ( exp > 0 ) {
+-		if ( exp & 1 )
+-			r *= n;
+-		exp >>= 1;
+-		n *= n;
++	if (*num=='-') sign=-1,num++;	/* Has sign? */
++	if (*num=='0') num++;			/* is zero */
++	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
++	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}	/* Fractional part? */
++	if (*num=='e' || *num=='E')		/* Exponent? */
++	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
++		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
+ 	}
+-	return r;
++
++	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
++
++	item->valuedouble=n;
++	item->valueint=(int64_t)n;
++	item->type=cJSON_Number;
++	return num;
+ }
+ 
++static int pow2gt (int x)	{	--x;	x|=x>>1;	x|=x>>2;	x|=x>>4;	x|=x>>8;	x|=x>>16;	return x+1;	}
+ 
+-/* Parse the input text to generate a number, and populate the result into item. */
+-static const char *parse_number( cJSON *item, const char *num )
++typedef struct {char *buffer; int length; int offset; } printbuffer;
++
++static char* ensure(printbuffer *p,int needed)
+ {
+-	int64_t i = 0;
+-	double f = 0;
+-	int isint = 1;
+-	int sign = 1, scale = 0, subscale = 0, signsubscale = 1;
+-
+-	/* Could use sscanf for this? */
+-	if ( *num == '-' ) {
+-		/* Has sign. */
+-		sign = -1;
+-		++num;
+-	}
+-	if ( *num == '0' )
+-		/* Is zero. */
+-		++num;
+-	if ( *num >= '1' && *num<='9' ) {
+-		/* Number. */
+-		do {
+-			i = ( i * 10 ) + ( *num - '0' );
+-			f = ( f * 10.0 ) + ( *num - '0' );
+-			++num;
+-		} while ( *num >= '0' && *num <= '9' );
+-	}
+-	if ( *num == '.' && num[1] >= '0' && num[1] <= '9' ) {
+-		/* Fractional part. */
+-		isint = 0;
+-		++num;
+-		do {
+-			f = ( f * 10.0 ) + ( *num++ - '0' );
+-			scale--;
+-		} while ( *num >= '0' && *num <= '9' );
+-	}
+-	if ( *num == 'e' || *num == 'E' ) {
+-		/* Exponent. */
+-		isint = 0;
+-		++num;
+-		if ( *num == '+' )
+-			++num;
+-		else if ( *num == '-' ) {
+-			/* With sign. */
+-			signsubscale = -1;
+-			++num;
+-		}
+-		while ( *num >= '0' && *num <= '9' )
+-			subscale = ( subscale * 10 ) + ( *num++ - '0' );
+-	}
+-
+-	/* Put it together. */
+-	if ( isint ) {
+-		/* Int: number = +/- number */
+-		i = sign * i;
+-		item->valueint = i;
+-		item->valuefloat = i;
+-	} else {
+-		/* Float: number = +/- number.fraction * 10^+/- exponent */
+-		f = sign * f * ipow( 10.0, scale + subscale * signsubscale );
+-		item->valueint = f;
+-		item->valuefloat = f;
+-	}
++	char *newbuffer;int newsize;
++	if (!p || !p->buffer) return 0;
++	needed+=p->offset;
++	if (needed<=p->length) return p->buffer+p->offset;
+ 
+-	item->type = cJSON_Number;
+-	return num;
++	newsize=pow2gt(needed);
++	newbuffer=(char*)cJSON_malloc(newsize);
++	if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
++	if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
++	cJSON_free(p->buffer);
++	p->length=newsize;
++	p->buffer=newbuffer;
++	return newbuffer+p->offset;
+ }
+ 
+-
+-/* Render the number nicely from the given item into a string. */
+-static char *print_number( cJSON *item )
++static int update(printbuffer *p)
+ {
+ 	char *str;
+-	double f, f2;
+-	int64_t i;
++	if (!p || !p->buffer) return 0;
++	str=p->buffer+p->offset;
++	return p->offset+strlen(str);
++}
+ 
+-	str = (char*) cJSON_malloc( 64 );
+-	if ( str ) {
+-		f = item->valuefloat;
+-		i = f;
+-		f2 = i;
+-		if ( f2 == f && item->valueint >= LLONG_MIN && item->valueint <= LLONG_MAX )
+-			sprintf( str, "%lld", (long long) item->valueint );
+-		else
+-			sprintf( str, "%g", item->valuefloat );
++/* Render the number nicely from the given item into a string. */
++static char *print_number(cJSON *item,printbuffer *p)
++{
++	char *str=0;
++	double d=item->valuedouble;
++	if (d==0)
++	{
++		if (p)	str=ensure(p,2);
++		else	str=(char*)cJSON_malloc(2);	/* special case for 0. */
++		if (str) strcpy(str,"0");
++	}
++	else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=LLONG_MAX && d>=LLONG_MIN)
++	{
++		if (p)	str=ensure(p,64);
++		else	str=(char*)cJSON_malloc(64);
++		if (str)	sprintf(str,"%lld",(long long) item->valueint);
++	}
++	else
++	{
++		if (p)	str=ensure(p,64);
++		else	str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
++		if (str)
++		{
++			if (fpclassify(d) != FP_ZERO && !isnormal(d))				sprintf(str,"null");
++			else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)	sprintf(str,"%.0f",d);
++			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)					sprintf(str,"%e",d);
++			else														sprintf(str,"%f",d);
++		}
+ 	}
+ 	return str;
+ }
+ 
++static unsigned parse_hex4(const char *str)
++{
++	unsigned h=0;
++	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
++	h=h<<4;str++;
++	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
++	h=h<<4;str++;
++	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
++	h=h<<4;str++;
++	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
++	return h;
++}
+ 
+ /* Parse the input text into an unescaped cstring, and populate item. */
+ static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+-
+-static const char *parse_string( cJSON *item, const char *str )
++static const char *parse_string(cJSON *item,const char *str,const char **ep)
+ {
+-	const char *ptr = str + 1;
+-	char *ptr2;
+-	char *out;
+-	int len = 0;
+-	unsigned uc, uc2;
+-
+-	if ( *str != '\"' ) {
+-		/* Not a string! */
+-		ep = str;
+-		return 0;
+-	}
+-	
+-	/* Skip escaped quotes. */
+-	while ( *ptr != '\"' && *ptr && ++len )
+-		if ( *ptr++ == '\\' )
+-			ptr++;
+-	
+-	if ( ! ( out = (char*) cJSON_malloc( len + 1 ) ) )
+-		return 0;
+-	
+-	ptr = str + 1;
+-	ptr2 = out;
+-	while ( *ptr != '\"' && *ptr ) {
+-		if ( *ptr != '\\' )
+-			*ptr2++ = *ptr++;
+-		else {
++	const char *ptr=str+1,*end_ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
++	if (*str!='\"') {*ep=str;return 0;}	/* not a string! */
++
++	while (*end_ptr!='\"' && *end_ptr && ++len) if (*end_ptr++ == '\\') end_ptr++;	/* Skip escaped quotes. */
++
++	out=(char*)cJSON_malloc(len+1);	/* This is how long we need for the string, roughly. */
++	if (!out) return 0;
++	item->valuestring=out; /* assign here so out will be deleted during cJSON_Delete() later */
++	item->type=cJSON_String;
++
++	ptr=str+1;ptr2=out;
++	while (ptr < end_ptr)
++	{
++		if (*ptr!='\\') *ptr2++=*ptr++;
++		else
++		{
+ 			ptr++;
+-			switch ( *ptr ) {
+-				case 'b': *ptr2++ ='\b'; break;
+-				case 'f': *ptr2++ ='\f'; break;
+-				case 'n': *ptr2++ ='\n'; break;
+-				case 'r': *ptr2++ ='\r'; break;
+-				case 't': *ptr2++ ='\t'; break;
+-				case 'u':
+-					/* Transcode utf16 to utf8. */
+-					/* Get the unicode char. */
+-					sscanf( ptr + 1,"%4x", &uc );
+-					ptr += 4;
+-					/* Check for invalid. */
+-					if ( ( uc >= 0xDC00 && uc <= 0xDFFF ) || uc == 0 )
+-						break;
+-
+-					/* UTF16 surrogate pairs. */
+-					if ( uc >= 0xD800 && uc <= 0xDBFF ) {
+-						if ( ptr[1] != '\\' || ptr[2] != 'u' )
+-							/* Missing second-half of surrogate. */
+-							break;
+-						sscanf( ptr + 3, "%4x", &uc2 );
+-						ptr += 6;
+-						if ( uc2 < 0xDC00 || uc2 > 0xDFFF )
+-							/* Invalid second-half of surrogate. */
+-							break;
+-						uc = 0x10000 | ( ( uc & 0x3FF ) << 10 ) | ( uc2 & 0x3FF );
++			switch (*ptr)
++			{
++				case 'b': *ptr2++='\b';	break;
++				case 'f': *ptr2++='\f';	break;
++				case 'n': *ptr2++='\n';	break;
++				case 'r': *ptr2++='\r';	break;
++				case 't': *ptr2++='\t';	break;
++				case 'u':	 /* transcode utf16 to utf8. */
++					uc=parse_hex4(ptr+1);ptr+=4;	/* get the unicode char. */
++					if (ptr >= end_ptr) {*ep=str;return 0;}	/* invalid */
++
++					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    {*ep=str;return 0;}	/* check for invalid.   */
++
++					if (uc>=0xD800 && uc<=0xDBFF)	/* UTF16 surrogate pairs.	*/
++					{
++						if (ptr+6 > end_ptr)    {*ep=str;return 0;}	/* invalid */
++						if (ptr[1]!='\\' || ptr[2]!='u')    {*ep=str;return 0;}	/* missing second-half of surrogate.    */
++						uc2=parse_hex4(ptr+3);ptr+=6;
++						if (uc2<0xDC00 || uc2>0xDFFF)       {*ep=str;return 0;}	/* invalid second-half of surrogate.    */
++						uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
+ 					}
+ 
+-					len = 4;
+-					if ( uc < 0x80 )
+-						len = 1;
+-					else if ( uc < 0x800 )
+-						len = 2;
+-					else if ( uc < 0x10000 )
+-						len = 3;
+-					ptr2 += len;
+-					
+-					switch ( len ) {
+-						case 4: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
+-						case 3: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
+-						case 2: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
+-						case 1: *--ptr2 = ( uc | firstByteMark[len] );
++					len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
++
++					switch (len) {
++						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
++						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
++						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
++						case 1: *--ptr2 =(uc | firstByteMark[len]);
+ 					}
+-					ptr2 += len;
++					ptr2+=len;
+ 					break;
+-				default:  *ptr2++ = *ptr; break;
++				default:  *ptr2++=*ptr; break;
+ 			}
+-			++ptr;
++			ptr++;
+ 		}
+ 	}
+-	*ptr2 = 0;
+-	if ( *ptr == '\"' )
+-		++ptr;
+-	item->valuestring = out;
+-	item->type = cJSON_String;
++	*ptr2=0;
++	if (*ptr=='\"') ptr++;
+ 	return ptr;
+ }
+ 
+-
+ /* Render the cstring provided to an escaped version that can be printed. */
+-static char *print_string_ptr( const char *str )
++static char *print_string_ptr(const char *str,printbuffer *p)
+ {
+-	const char *ptr;
+-	char *ptr2, *out;
+-	int len = 0;
+-	unsigned char token;
+-	
+-	if ( ! str )
+-		return cJSON_strdup( "" );
+-	ptr = str;
+-	while ( ( token = *ptr ) && ++len ) {
+-		if ( strchr( "\"\\\b\f\n\r\t", token ) )
+-			++len;
+-		else if ( token < 32 )
+-			len += 5;
+-		++ptr;
+-	}
+-	
+-	if ( ! ( out = (char*) cJSON_malloc( len + 3 ) ) )
+-		return 0;
+-
+-	ptr2 = out;
+-	ptr = str;
+-	*ptr2++ = '\"';
+-	while ( *ptr ) {
+-		if ( (unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\' )
+-			*ptr2++ = *ptr++;
+-		else {
+-			*ptr2++ = '\\';
+-			switch ( token = *ptr++ ) {
+-				case '\\': *ptr2++ = '\\'; break;
+-				case '\"': *ptr2++ = '\"'; break;
+-				case '\b': *ptr2++ = 'b'; break;
+-				case '\f': *ptr2++ = 'f'; break;
+-				case '\n': *ptr2++ = 'n'; break;
+-				case '\r': *ptr2++ = 'r'; break;
+-				case '\t': *ptr2++ = 't'; break;
+-				default:
+-				/* Escape and print. */
+-				sprintf( ptr2, "u%04x", token );
+-				ptr2 += 5;
+-				break;
++	const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
++
++	if (!str)
++	{
++		if (p)	out=ensure(p,3);
++		else	out=(char*)cJSON_malloc(3);
++		if (!out) return 0;
++		strcpy(out,"\"\"");
++		return out;
++	}
++
++	for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
++	if (!flag)
++	{
++		len=ptr-str;
++		if (p) out=ensure(p,len+3);
++		else		out=(char*)cJSON_malloc(len+3);
++		if (!out) return 0;
++		ptr2=out;*ptr2++='\"';
++		strcpy(ptr2,str);
++		ptr2[len]='\"';
++		ptr2[len+1]=0;
++		return out;
++	}
++
++	ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
++
++	if (p)	out=ensure(p,len+3);
++	else	out=(char*)cJSON_malloc(len+3);
++	if (!out) return 0;
++
++	ptr2=out;ptr=str;
++	*ptr2++='\"';
++	while (*ptr)
++	{
++		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
++		else
++		{
++			*ptr2++='\\';
++			switch (token=*ptr++)
++			{
++				case '\\':	*ptr2++='\\';	break;
++				case '\"':	*ptr2++='\"';	break;
++				case '\b':	*ptr2++='b';	break;
++				case '\f':	*ptr2++='f';	break;
++				case '\n':	*ptr2++='n';	break;
++				case '\r':	*ptr2++='r';	break;
++				case '\t':	*ptr2++='t';	break;
++				default: sprintf(ptr2,"u%04x",token);ptr2+=5;	break;	/* escape and print */
+ 			}
+ 		}
+ 	}
+-	*ptr2++ = '\"';
+-	*ptr2++ = 0;
++	*ptr2++='\"';*ptr2++=0;
+ 	return out;
+ }
+-
+-
+ /* Invote print_string_ptr (which is useful) on an item. */
+-static char *print_string( cJSON *item )
+-{
+-	return print_string_ptr( item->valuestring );
+-}
+-
++static char *print_string(cJSON *item,printbuffer *p)	{return print_string_ptr(item->valuestring,p);}
+ 
+ /* Predeclare these prototypes. */
+-static const char *parse_value( cJSON *item, const char *value );
+-static char *print_value( cJSON *item, int depth, int fmt );
+-static const char *parse_array( cJSON *item, const char *value );
+-static char *print_array( cJSON *item, int depth, int fmt );
+-static const char *parse_object( cJSON *item, const char *value );
+-static char *print_object( cJSON *item, int depth, int fmt );
+-
+-/* Utility to jump whitespace and cr/lf. */
+-static const char *skip( const char *in )
+-{
+-	while ( in && *in && (unsigned char) *in <= 32 )
+-		in++;
+-	return in;
+-}
++static const char *parse_value(cJSON *item,const char *value,const char **ep);
++static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
++static const char *parse_array(cJSON *item,const char *value,const char **ep);
++static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
++static const char *parse_object(cJSON *item,const char *value,const char **ep);
++static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
+ 
++/* Utility to jump whitespace and cr/lf */
++static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
+ 
+ /* Parse an object - create a new root, and populate. */
+-cJSON *cJSON_Parse( const char *value )
++cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
+ {
+-	cJSON *c;
+-	ep = 0;
+-	if ( ! ( c = cJSON_New_Item() ) )
+-		return 0;	/* memory fail */
+-
+-	if ( ! parse_value( c, skip( value ) ) ) {
+-		cJSON_Delete( c );
+-		return 0;
+-	}
++	const char *end=0,**ep=return_parse_end?return_parse_end:&global_ep;
++	cJSON *c=cJSON_New_Item();
++	*ep=0;
++	if (!c) return 0;       /* memory fail */
++
++	end=parse_value(c,skip(value),ep);
++	if (!end)	{cJSON_Delete(c);return 0;}	/* parse failure. ep is set. */
++
++	/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
++	if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);*ep=end;return 0;}}
++	if (return_parse_end) *return_parse_end=end;
+ 	return c;
+ }
+-
++/* Default options for cJSON_Parse */
++cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
+ 
+ /* Render a cJSON item/entity/structure to text. */
+-char *cJSON_Print( cJSON *item )
+-{
+-	return print_value( item, 0, 1 );
+-}
+-char *cJSON_PrintUnformatted( cJSON *item )
++char *cJSON_Print(cJSON *item)				{return print_value(item,0,1,0);}
++char *cJSON_PrintUnformatted(cJSON *item)	{return print_value(item,0,0,0);}
++
++char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
+ {
+-	return print_value( item, 0, 0 );
++	printbuffer p;
++	p.buffer=(char*)cJSON_malloc(prebuffer);
++	p.length=prebuffer;
++	p.offset=0;
++	return print_value(item,0,fmt,&p);
+ }
+ 
+ 
+ /* Parser core - when encountering text, process appropriately. */
+-static const char *parse_value( cJSON *item, const char *value )
++static const char *parse_value(cJSON *item,const char *value,const char **ep)
+ {
+-	if ( ! value )
+-		return 0;	/* Fail on null. */
+-	if ( ! strncmp( value, "null", 4 ) ) {
+-		item->type = cJSON_NULL;
+-		return value + 4;
+-	}
+-	if ( ! strncmp( value, "false", 5 ) ) {
+-		item->type = cJSON_False;
+-		return value + 5;
+-	}
+-	if ( ! strncmp( value, "true", 4 ) ) {
+-		item->type = cJSON_True;
+-		item->valueint = 1;
+-		return value + 4;
+-	}
+-	if ( *value == '\"' )
+-		return parse_string( item, value );
+-	if ( *value == '-' || ( *value >= '0' && *value <= '9' ) )
+-		return parse_number( item, value );
+-	if ( *value == '[' )
+-		return parse_array( item, value );
+-	if ( *value == '{' )
+-		return parse_object( item, value );
+-
+-	/* Fail. */
+-	ep = value;
+-	return 0;
+-}
++	if (!value)						return 0;	/* Fail on null. */
++	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
++	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
++	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
++	if (*value=='\"')				{ return parse_string(item,value,ep); }
++	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
++	if (*value=='[')				{ return parse_array(item,value,ep); }
++	if (*value=='{')				{ return parse_object(item,value,ep); }
+ 
++	*ep=value;return 0;	/* failure. */
++}
+ 
+ /* Render a value to text. */
+-static char *print_value( cJSON *item, int depth, int fmt )
++static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
+ {
+-	char *out = 0;
+-
+-	if ( ! item )
+-		return 0;
+-	switch ( ( item->type ) & 255 ) {
+-		case cJSON_NULL:   out = cJSON_strdup( "null" ); break;
+-		case cJSON_False:  out = cJSON_strdup( "false" ); break;
+-		case cJSON_True:   out = cJSON_strdup( "true" ); break;
+-		case cJSON_Number: out = print_number( item ); break;
+-		case cJSON_String: out = print_string( item ); break;
+-		case cJSON_Array:  out = print_array( item, depth, fmt ); break;
+-		case cJSON_Object: out = print_object( item, depth, fmt ); break;
++	char *out=0;
++	if (!item) return 0;
++	if (p)
++	{
++		switch ((item->type)&255)
++		{
++			case cJSON_NULL:	{out=ensure(p,5);	if (out) strcpy(out,"null");	break;}
++			case cJSON_False:	{out=ensure(p,6);	if (out) strcpy(out,"false");	break;}
++			case cJSON_True:	{out=ensure(p,5);	if (out) strcpy(out,"true");	break;}
++			case cJSON_Number:	out=print_number(item,p);break;
++			case cJSON_String:	out=print_string(item,p);break;
++			case cJSON_Array:	out=print_array(item,depth,fmt,p);break;
++			case cJSON_Object:	out=print_object(item,depth,fmt,p);break;
++		}
++	}
++	else
++	{
++		switch ((item->type)&255)
++		{
++			case cJSON_NULL:	out=cJSON_strdup("null");	break;
++			case cJSON_False:	out=cJSON_strdup("false");break;
++			case cJSON_True:	out=cJSON_strdup("true"); break;
++			case cJSON_Number:	out=print_number(item,0);break;
++			case cJSON_String:	out=print_string(item,0);break;
++			case cJSON_Array:	out=print_array(item,depth,fmt,0);break;
++			case cJSON_Object:	out=print_object(item,depth,fmt,0);break;
++		}
+ 	}
+ 	return out;
+ }
+ 
+-
+ /* Build an array from input text. */
+-static const char *parse_array( cJSON *item, const char *value )
++static const char *parse_array(cJSON *item,const char *value,const char **ep)
+ {
+ 	cJSON *child;
++	if (*value!='[')	{*ep=value;return 0;}	/* not an array! */
+ 
+-	if ( *value != '[' ) {
+-		/* Not an array! */
+-		ep = value;
+-		return 0;
+-	}
+-
+-	item->type = cJSON_Array;
+-	value = skip( value + 1 );
+-	if ( *value == ']' )
+-		return value + 1;	/* empty array. */
+-
+-	if ( ! ( item->child = child = cJSON_New_Item() ) )
+-		return 0;		 /* memory fail */
+-	if ( ! ( value = skip( parse_value( child, skip( value ) ) ) ) )
+-		return 0;
++	item->type=cJSON_Array;
++	value=skip(value+1);
++	if (*value==']') return value+1;	/* empty array. */
++
++	item->child=child=cJSON_New_Item();
++	if (!item->child) return 0;		 /* memory fail */
++	value=skip(parse_value(child,skip(value),ep));	/* skip any spacing, get the value. */
++	if (!value) return 0;
+ 
+-	while ( *value == ',' ) {
++	while (*value==',')
++	{
+ 		cJSON *new_item;
+-		if ( ! ( new_item = cJSON_New_Item() ) )
+-			return 0;	/* memory fail */
+-		child->next = new_item;
+-		new_item->prev = child;
+-		child = new_item;
+-		if ( ! ( value = skip( parse_value( child, skip( value+1 ) ) ) ) )
+-			return 0;	/* memory fail */
++		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
++		child->next=new_item;new_item->prev=child;child=new_item;
++		value=skip(parse_value(child,skip(value+1),ep));
++		if (!value) return 0;	/* memory fail */
+ 	}
+ 
+-	if ( *value == ']' )
+-		return value + 1;	/* end of array */
+-	/* Malformed. */
+-	ep = value;
+-	return 0;
++	if (*value==']') return value+1;	/* end of array */
++	*ep=value;return 0;	/* malformed. */
+ }
+ 
+-
+ /* Render an array to text */
+-static char *print_array( cJSON *item, int depth, int fmt )
++static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
+ {
+ 	char **entries;
+-	char *out = 0, *ptr, *ret;
+-	int len = 5;
+-	cJSON *child = item->child;
+-	int numentries = 0, i = 0, fail = 0;
+-	
++	char *out=0,*ptr,*ret;int len=5;
++	cJSON *child=item->child;
++	int numentries=0,i=0,fail=0;
++	size_t tmplen=0;
++
+ 	/* How many entries in the array? */
+-	while ( child ) {
+-		++numentries;
+-		child = child->next;
+-	}
+-	/* Allocate an array to hold the values for each. */
+-	if ( ! ( entries = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) )
+-		return 0;
+-	memset( entries, 0, numentries * sizeof(char*) );
+-	/* Retrieve all the results. */
+-	child = item->child;
+-	while ( child && ! fail ) {
+-		ret = print_value( child, depth + 1, fmt );
+-		entries[i++] = ret;
+-		if ( ret )
+-			len += strlen( ret ) + 2 + ( fmt ? 1 : 0 );
+-		else
+-			fail = 1;
+-		child = child -> next;
++	while (child) numentries++,child=child->next;
++	/* Explicitly handle numentries==0 */
++	if (!numentries)
++	{
++		if (p)	out=ensure(p,3);
++		else	out=(char*)cJSON_malloc(3);
++		if (out) strcpy(out,"[]");
++		return out;
++	}
++
++	if (p)
++	{
++		/* Compose the output array. */
++		i=p->offset;
++		ptr=ensure(p,1);if (!ptr) return 0;	*ptr='[';	p->offset++;
++		child=item->child;
++		while (child && !fail)
++		{
++			print_value(child,depth+1,fmt,p);
++			p->offset=update(p);
++			if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
++			child=child->next;
++		}
++		ptr=ensure(p,2);if (!ptr) return 0;	*ptr++=']';*ptr=0;
++		out=(p->buffer)+i;
+ 	}
+-	
+-	/* If we didn't fail, try to malloc the output string. */
+-	if ( ! fail ) {
+-		out = (char*) cJSON_malloc( len );
+-		if ( ! out )
+-			fail = 1;
+-	}
+-
+-	/* Handle failure. */
+-	if ( fail ) {
+-		for ( i = 0; i < numentries; ++i )
+-			if ( entries[i] )
+-				cJSON_free( entries[i] );
+-		cJSON_free( entries );
+-		return 0;
+-	}
+-	
+-	/* Compose the output array. */
+-	*out = '[';
+-	ptr = out + 1;
+-	*ptr = 0;
+-	for ( i = 0; i < numentries; ++i ) {
+-		strcpy( ptr, entries[i] );
+-		ptr += strlen( entries[i] );
+-		if ( i != numentries - 1 ) {
+-			*ptr++ = ',';
+-			if ( fmt )
+-				*ptr++ = ' ';
+-			*ptr = 0;
+-		}
+-		cJSON_free( entries[i] );
+-	}
+-	cJSON_free( entries );
+-	*ptr++ = ']';
+-	*ptr++ = 0;
+-	return out;	
+-}
+-
+-
+-/* Build an object from the text. */
+-static const char *parse_object( cJSON *item, const char *value )
+-{
+-	cJSON *child;
++	else
++	{
++		/* Allocate an array to hold the values for each */
++		entries=(char**)cJSON_malloc(numentries*sizeof(char*));
++		if (!entries) return 0;
++		memset(entries,0,numentries*sizeof(char*));
++		/* Retrieve all the results: */
++		child=item->child;
++		while (child && !fail)
++		{
++			ret=print_value(child,depth+1,fmt,0);
++			entries[i++]=ret;
++			if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
++			child=child->next;
++		}
+ 
+-	if ( *value != '{' ) {
+-		/* Not an object! */
+-		ep = value;
+-		return 0;
+-	}
+-	
+-	item->type = cJSON_Object;
+-	value =skip( value + 1 );
+-	if ( *value == '}' )
+-		return value + 1;	/* empty array. */
+-	
+-	if ( ! ( item->child = child = cJSON_New_Item() ) )
+-		return 0;
+-	if ( ! ( value = skip( parse_string( child, skip( value ) ) ) ) )
+-		return 0;
+-	child->string = child->valuestring;
+-	child->valuestring = 0;
+-	if ( *value != ':' ) {
+-		/* Fail! */
+-		ep = value;
+-		return 0;
+-	}
+-	if ( ! ( value = skip( parse_value( child, skip( value + 1 ) ) ) ) )
+-		return 0;
+-	
+-	while ( *value == ',' ) {
+-		cJSON *new_item;
+-		if ( ! ( new_item = cJSON_New_Item() ) )
+-			return 0;	/* memory fail */
+-		child->next = new_item;
+-		new_item->prev = child;
+-		child = new_item;
+-		if ( ! ( value = skip( parse_string( child, skip( value + 1 ) ) ) ) )
+-			return 0;
+-		child->string = child->valuestring;
+-		child->valuestring = 0;
+-		if ( *value != ':' ) {
+-			/* Fail! */
+-			ep = value;
++		/* If we didn't fail, try to malloc the output string */
++		if (!fail)	out=(char*)cJSON_malloc(len);
++		/* If that fails, we fail. */
++		if (!out) fail=1;
++
++		/* Handle failure. */
++		if (fail)
++		{
++			for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
++			cJSON_free(entries);
+ 			return 0;
+ 		}
+-		if ( ! ( value = skip( parse_value( child, skip( value + 1 ) ) ) ) )
+-			return 0;
+-	}
+-	
+-	if ( *value == '}' )
+-		return value + 1;	/* end of array */
+-	/* Malformed. */
+-	ep = value;
+-	return 0;
+-}
+ 
+-
+-/* Render an object to text. */
+-static char *print_object( cJSON *item, int depth, int fmt )
+-{
+-	char **entries = 0, **names = 0;
+-	char *out = 0, *ptr, *ret, *str;
+-	int len = 7, i = 0, j;
+-	cJSON *child = item->child;
+-	int numentries = 0, fail = 0;
+-
+-	/* Count the number of entries. */
+-	while ( child ) {
+-		++numentries;
+-		child = child->next;
+-	}
+-	/* Allocate space for the names and the objects. */
+-	if ( ! ( entries = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) )
+-		return 0;
+-	if ( ! ( names = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) ) {
+-		cJSON_free( entries );
+-		return 0;
+-	}
+-	memset( entries, 0, sizeof(char*) * numentries );
+-	memset( names, 0, sizeof(char*) * numentries );
+-
+-	/* Collect all the results into our arrays. */
+-	child = item->child;
+-	++depth;
+-	if ( fmt )
+-		len += depth;
+-	while ( child ) {
+-		names[i] = str = print_string_ptr( child->string );
+-		entries[i++] = ret = print_value( child, depth, fmt );
+-		if ( str && ret )
+-			len += strlen( ret ) + strlen( str ) + 2 + ( fmt ? 2 + depth : 0 );
+-		else
+-			fail = 1;
+-		child = child->next;
+-	}
+-	
+-	/* Try to allocate the output string. */
+-	if ( ! fail ) {
+-		out = (char*) cJSON_malloc( len );
+-		if ( ! out )
+-			fail = 1;
+-	}
+-
+-	/* Handle failure. */
+-	if ( fail ) {
+-		for ( i = 0; i < numentries; ++i ) {
+-			if ( names[i] )
+-				cJSON_free( names[i] );
+-			if ( entries[i] )
+-				cJSON_free( entries[i] );
+-		}
+-		cJSON_free( names );
+-		cJSON_free( entries );
+-		return 0;
+-	}
+-	
+-	/* Compose the output. */
+-	*out = '{';
+-	ptr = out + 1;
+-	if ( fmt )
+-		*ptr++ = '\n';
+-	*ptr = 0;
+-	for ( i = 0; i < numentries; ++i ) {
+-		if ( fmt )
+-			for ( j = 0; j < depth; ++j )
+-				*ptr++ = '\t';
+-		strcpy( ptr, names[i] );
+-		ptr += strlen( names[i] );
+-		*ptr++ = ':';
+-		if ( fmt )
+-			*ptr++ = '\t';
+-		strcpy( ptr, entries[i] );
+-		ptr += strlen( entries[i] );
+-		if ( i != numentries - 1 )
+-			*ptr++ = ',';
+-		if ( fmt )
+-			*ptr++ = '\n';
+-		*ptr = 0;
+-		cJSON_free( names[i] );
+-		cJSON_free( entries[i] );
+-	}
+-	
+-	cJSON_free( names );
+-	cJSON_free( entries );
+-	if ( fmt )
+-		for ( i = 0; i < depth - 1; ++i )
+-			*ptr++ = '\t';
+-	*ptr++ = '}';
+-	*ptr++ = 0;
+-	return out;	
+-}
+-
+-
+-int cJSON_GetArraySize( cJSON *array )
+-{
+-	cJSON *c = array->child;
+-	int i = 0;
+-	while ( c ) {
+-		++i;
+-		c = c->next;
+-	}
+-	return i;
+-}
+-
+-
+-cJSON *cJSON_GetArrayItem( cJSON *array, int item )
+-{
+-	cJSON *c = array->child;
+-	while ( c && item > 0 ) {
+-		--item;
+-		c = c->next;
++		/* Compose the output array. */
++		*out='[';
++		ptr=out+1;*ptr=0;
++		for (i=0;i<numentries;i++)
++		{
++			tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
++			if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
++			cJSON_free(entries[i]);
++		}
++		cJSON_free(entries);
++		*ptr++=']';*ptr++=0;
+ 	}
+-	return c;
+-}
+-
+-
+-cJSON *cJSON_GetObjectItem( cJSON *object, const char *string )
+-{
+-	cJSON *c = object->child;
+-	while ( c && cJSON_strcasecmp( c->string, string ) )
+-		c = c->next;
+-	return c;
+-}
+-
+-
+-/* Utility for array list handling. */
+-static void suffix_object( cJSON *prev, cJSON *item )
+-{
+-	prev->next = item;
+-	item->prev = prev;
++	return out;
+ }
+ 
+-
+-/* Utility for handling references. */
+-static cJSON *create_reference( cJSON *item )
++/* Build an object from the text. */
++static const char *parse_object(cJSON *item,const char *value,const char **ep)
+ {
+-	cJSON *ref;
+-	if ( ! ( ref = cJSON_New_Item() ) )
+-		return 0;
+-	memcpy( ref, item, sizeof(cJSON) );
+-	ref->string = 0;
+-	ref->type |= cJSON_IsReference;
+-	ref->next = ref->prev = 0;
+-	return ref;
+-}
++	cJSON *child;
++	if (*value!='{')	{*ep=value;return 0;}	/* not an object! */
+ 
++	item->type=cJSON_Object;
++	value=skip(value+1);
++	if (*value=='}') return value+1;	/* empty array. */
++
++	item->child=child=cJSON_New_Item();
++	if (!item->child) return 0;
++	value=skip(parse_string(child,skip(value),ep));
++	if (!value) return 0;
++	child->string=child->valuestring;child->valuestring=0;
++	if (*value!=':') {*ep=value;return 0;}	/* fail! */
++	value=skip(parse_value(child,skip(value+1),ep));	/* skip any spacing, get the value. */
++	if (!value) return 0;
+ 
+-/* Add item to array/object. */
+-void cJSON_AddItemToArray( cJSON *array, cJSON *item )
+-{
+-	cJSON *c = array->child;
+-	if ( ! item )
+-		return;
+-	if ( ! c ) {
+-		array->child = item;
+-	} else {
+-		while ( c && c->next )
+-			c = c->next;
+-		suffix_object( c, item );
++	while (*value==',')
++	{
++		cJSON *new_item;
++		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
++		child->next=new_item;new_item->prev=child;child=new_item;
++		value=skip(parse_string(child,skip(value+1),ep));
++		if (!value) return 0;
++		child->string=child->valuestring;child->valuestring=0;
++		if (*value!=':') {*ep=value;return 0;}	/* fail! */
++		value=skip(parse_value(child,skip(value+1),ep));	/* skip any spacing, get the value. */
++		if (!value) return 0;
+ 	}
+-}
+ 
+-void cJSON_AddItemToObject( cJSON *object, const char *string, cJSON *item )
+-{
+-	if ( ! item )
+-		return;
+-	if ( item->string )
+-		cJSON_free( item->string );
+-	item->string = cJSON_strdup( string );
+-	cJSON_AddItemToArray( object, item );
+-}
+-
+-void cJSON_AddItemReferenceToArray( cJSON *array, cJSON *item )
+-{
+-	cJSON_AddItemToArray( array, create_reference( item ) );
++	if (*value=='}') return value+1;	/* end of array */
++	*ep=value;return 0;	/* malformed. */
+ }
+ 
+-void cJSON_AddItemReferenceToObject( cJSON *object, const char *string, cJSON *item )
+-{
+-	cJSON_AddItemToObject( object, string, create_reference( item ) );
+-}
+-
+-cJSON *cJSON_DetachItemFromArray( cJSON *array, int which )
+-{
+-	cJSON *c = array->child;
+-	while ( c && which > 0 ) {
+-		c = c->next;
+-		--which;
+-	}
+-	if ( ! c )
+-		return 0;
+-	if ( c->prev )
+-		c->prev->next = c->next;
+-	if ( c->next ) c->next->prev = c->prev;
+-	if ( c == array->child )
+-		array->child = c->next;
+-	c->prev = c->next = 0;
+-	return c;
+-}
+-
+-void cJSON_DeleteItemFromArray( cJSON *array, int which )
++/* Render an object to text. */
++static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
+ {
+-	cJSON_Delete( cJSON_DetachItemFromArray( array, which ) );
+-}
++	char **entries=0,**names=0;
++	char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
++	cJSON *child=item->child;
++	int numentries=0,fail=0;
++	size_t tmplen=0;
++	/* Count the number of entries. */
++	while (child) numentries++,child=child->next;
++	/* Explicitly handle empty object case */
++	if (!numentries)
++	{
++		if (p) out=ensure(p,fmt?depth+4:3);
++		else	out=(char*)cJSON_malloc(fmt?depth+4:3);
++		if (!out)	return 0;
++		ptr=out;*ptr++='{';
++		if (fmt) {*ptr++='\n';for (i=0;i<depth;i++) *ptr++='\t';}
++		*ptr++='}';*ptr++=0;
++		return out;
++	}
++	if (p)
++	{
++		/* Compose the output: */
++		i=p->offset;
++		len=fmt?2:1;	ptr=ensure(p,len+1);	if (!ptr) return 0;
++		*ptr++='{';	if (fmt) *ptr++='\n';	*ptr=0;	p->offset+=len;
++		child=item->child;depth++;
++		while (child)
++		{
++			if (fmt)
++			{
++				ptr=ensure(p,depth);	if (!ptr) return 0;
++				for (j=0;j<depth;j++) *ptr++='\t';
++				p->offset+=depth;
++			}
++			print_string_ptr(child->string,p);
++			p->offset=update(p);
+ 
+-cJSON *cJSON_DetachItemFromObject( cJSON *object, const char *string )
+-{
+-	int i = 0;
+-	cJSON *c = object->child;
+-	while ( c && cJSON_strcasecmp( c->string, string ) ) {
+-		++i;
+-		c = c->next;
++			len=fmt?2:1;
++			ptr=ensure(p,len);	if (!ptr) return 0;
++			*ptr++=':';if (fmt) *ptr++='\t';
++			p->offset+=len;
++
++			print_value(child,depth,fmt,p);
++			p->offset=update(p);
++
++			len=(fmt?1:0)+(child->next?1:0);
++			ptr=ensure(p,len+1); if (!ptr) return 0;
++			if (child->next) *ptr++=',';
++			if (fmt) *ptr++='\n';*ptr=0;
++			p->offset+=len;
++			child=child->next;
++		}
++		ptr=ensure(p,fmt?(depth+1):2);	 if (!ptr) return 0;
++		if (fmt)	for (i=0;i<depth-1;i++) *ptr++='\t';
++		*ptr++='}';*ptr=0;
++		out=(p->buffer)+i;
+ 	}
+-	if ( c )
+-		return cJSON_DetachItemFromArray( object, i );
+-	return 0;
+-}
+-
+-void cJSON_DeleteItemFromObject( cJSON *object, const char *string )
+-{
+-	cJSON_Delete( cJSON_DetachItemFromObject( object, string ) );
+-}
+-
+-/* Replace array/object items with new ones. */
+-void cJSON_ReplaceItemInArray( cJSON *array, int which, cJSON *newitem )
+-{
+-	cJSON *c = array->child;
+-	while ( c && which > 0 ) {
+-		c = c->next;
+-		--which;
+-	}
+-	if ( ! c )
+-		return;
+-	newitem->next = c->next;
+-	newitem->prev = c->prev;
+-	if ( newitem->next )
+-		newitem->next->prev = newitem;
+-	if ( c == array->child )
+-		array->child = newitem;
+ 	else
+-		newitem->prev->next = newitem;
+-	c->next = c->prev = 0;
+-	cJSON_Delete( c );
+-}
+-
+-void cJSON_ReplaceItemInObject( cJSON *object, const char *string, cJSON *newitem )
+-{
+-	int i = 0;
+-	cJSON *c = object->child;
+-	while ( c && cJSON_strcasecmp( c->string, string ) ) {
+-		++i;
+-		c = c->next;
+-	}
+-	if ( c ) {
+-		newitem->string = cJSON_strdup( string );
+-		cJSON_ReplaceItemInArray( object, i, newitem );
+-	}
+-}
+-
+-
+-/* Create basic types: */
+-
+-cJSON *cJSON_CreateNull( void )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = cJSON_NULL;
+-	return item;
+-}
+-
+-cJSON *cJSON_CreateTrue( void )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = cJSON_True;
+-	return item;
+-}
+-
+-cJSON *cJSON_CreateFalse( void )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = cJSON_False;
+-	return item;
+-}
+-
+-cJSON *cJSON_CreateBool( int b )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = b ? cJSON_True : cJSON_False;
+-	return item;
+-}
++	{
++		/* Allocate space for the names and the objects */
++		entries=(char**)cJSON_malloc(numentries*sizeof(char*));
++		if (!entries) return 0;
++		names=(char**)cJSON_malloc(numentries*sizeof(char*));
++		if (!names) {cJSON_free(entries);return 0;}
++		memset(entries,0,sizeof(char*)*numentries);
++		memset(names,0,sizeof(char*)*numentries);
++
++		/* Collect all the results into our arrays: */
++		child=item->child;depth++;if (fmt) len+=depth;
++		while (child && !fail)
++		{
++			names[i]=str=print_string_ptr(child->string,0);
++			entries[i++]=ret=print_value(child,depth,fmt,0);
++			if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
++			child=child->next;
++		}
+ 
+-cJSON *cJSON_CreateInt( int64_t num )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item ) {
+-		item->type = cJSON_Number;
+-		item->valuefloat = num;
+-		item->valueint = num;
+-	}
+-	return item;
+-}
++		/* Try to allocate the output string */
++		if (!fail)	out=(char*)cJSON_malloc(len);
++		if (!out) fail=1;
++
++		/* Handle failure */
++		if (fail)
++		{
++			for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
++			cJSON_free(names);cJSON_free(entries);
++			return 0;
++		}
+ 
+-cJSON *cJSON_CreateFloat( double num )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item ) {
+-		item->type = cJSON_Number;
+-		item->valuefloat = num;
+-		item->valueint = num;
+-	}
+-	return item;
+-}
++		/* Compose the output: */
++		*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
++		for (i=0;i<numentries;i++)
++		{
++			if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
++			tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
++			*ptr++=':';if (fmt) *ptr++='\t';
++			strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
++			if (i!=numentries-1) *ptr++=',';
++			if (fmt) *ptr++='\n';*ptr=0;
++			cJSON_free(names[i]);cJSON_free(entries[i]);
++		}
+ 
+-cJSON *cJSON_CreateString( const char *string )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item ) {
+-		item->type = cJSON_String;
+-		item->valuestring = cJSON_strdup( string );
++		cJSON_free(names);cJSON_free(entries);
++		if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
++		*ptr++='}';*ptr++=0;
+ 	}
+-	return item;
+-}
+-
+-cJSON *cJSON_CreateArray( void )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = cJSON_Array;
+-	return item;
+-}
+-
+-cJSON *cJSON_CreateObject( void )
+-{
+-	cJSON *item = cJSON_New_Item();
+-	if ( item )
+-		item->type = cJSON_Object;
+-	return item;
++	return out;
+ }
+ 
++/* Get Array size/item / object item. */
++int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
++cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array?array->child:0;while (c && item>0) item--,c=c->next; return c;}
++cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object?object->child:0;while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
++int cJSON_HasObjectItem(cJSON *object,const char *string)		{return cJSON_GetObjectItem(object,string)?1:0;}
+ 
+-/* Create Arrays. */
++/* Utility for array list handling. */
++static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
++/* Utility for handling references. */
++static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
+ 
+-cJSON *cJSON_CreateIntArray( int64_t *numbers, int count )
+-{
+-	int i;
+-	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+-	for ( i = 0; a && i < count; ++i ) {
+-		n = cJSON_CreateInt( numbers[i] );
+-		if ( ! i )
+-			a->child = n;
+-		else
+-			suffix_object( p, n );
+-		p = n;
+-	}
+-	return a;
+-}
++/* Add item to array/object. */
++void   cJSON_AddItemToArray(cJSON *array, cJSON *item)						{cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
++void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)	{if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
++void   cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item)	{if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
++void	cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)						{cJSON_AddItemToArray(array,create_reference(item));}
++void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)	{cJSON_AddItemToObject(object,string,create_reference(item));}
++
++cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)			{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
++	if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
++void   cJSON_DeleteItemFromArray(cJSON *array,int which)			{cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
++cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
++void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
+ 
+-cJSON *cJSON_CreateFloatArray( double *numbers, int count )
+-{
+-	int i;
+-	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+-	for ( i = 0; a && i < count; ++i ) {
+-		n = cJSON_CreateFloat( numbers[i] );
+-		if ( ! i )
+-			a->child = n;
+-		else
+-			suffix_object( p, n );
+-		p = n;
+-	}
+-	return a;
+-}
++/* Replace array/object items with new ones. */
++void   cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem)		{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
++	newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
++void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)		{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
++	newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
++	if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
++void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
+ 
+-cJSON *cJSON_CreateStringArray( const char **strings, int count )
+-{
+-	int i;
+-	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+-	for ( i = 0; a && i < count; ++i ) {
+-		n = cJSON_CreateString( strings[i] );
+-		if ( ! i )
+-			a->child = n;
+-		else
+-			suffix_object( p, n );
+-		p = n;
++/* Create basic types: */
++cJSON *cJSON_CreateNull(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
++cJSON *cJSON_CreateTrue(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
++cJSON *cJSON_CreateFalse(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
++cJSON *cJSON_CreateBool(int b)					{cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
++cJSON *cJSON_CreateNumber(double num)			{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int64_t)num;}return item;}
++cJSON *cJSON_CreateString(const char *string)	{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);if(!item->valuestring){cJSON_Delete(item);return 0;}}return item;}
++cJSON *cJSON_CreateArray(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
++cJSON *cJSON_CreateObject(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
++
++/* Create Arrays: */
++cJSON *cJSON_CreateIntArray(const int *numbers,int count)		{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
++cJSON *cJSON_CreateFloatArray(const float *numbers,int count)	{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
++cJSON *cJSON_CreateDoubleArray(const double *numbers,int count)	{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
++cJSON *cJSON_CreateStringArray(const char **strings,int count)	{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
++
++/* Duplication */
++cJSON *cJSON_Duplicate(cJSON *item,int recurse)
++{
++	cJSON *newitem,*cptr,*nptr=0,*newchild;
++	/* Bail on bad ptr */
++	if (!item) return 0;
++	/* Create new item */
++	newitem=cJSON_New_Item();
++	if (!newitem) return 0;
++	/* Copy over all vars */
++	newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
++	if (item->valuestring)	{newitem->valuestring=cJSON_strdup(item->valuestring);	if (!newitem->valuestring)	{cJSON_Delete(newitem);return 0;}}
++	if (item->string)		{newitem->string=cJSON_strdup(item->string);			if (!newitem->string)		{cJSON_Delete(newitem);return 0;}}
++	/* If non-recursive, then we're done! */
++	if (!recurse) return newitem;
++	/* Walk the ->next chain for the child. */
++	cptr=item->child;
++	while (cptr)
++	{
++		newchild=cJSON_Duplicate(cptr,1);		/* Duplicate (with recurse) each item in the ->next chain */
++		if (!newchild) {cJSON_Delete(newitem);return 0;}
++		if (nptr)	{nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}	/* If newitem->child already set, then crosswire ->prev and ->next and move on */
++		else		{newitem->child=newchild;nptr=newchild;}					/* Set newitem->child and move to it */
++		cptr=cptr->next;
++	}
++	return newitem;
++}
++
++void cJSON_Minify(char *json)
++{
++	char *into=json;
++	while (*json)
++	{
++		if (*json==' ') json++;
++		else if (*json=='\t') json++;	/* Whitespace characters. */
++		else if (*json=='\r') json++;
++		else if (*json=='\n') json++;
++		else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;	/* double-slash comments, to end of line. */
++		else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}	/* multiline comments. */
++		else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
++		else *into++=*json++;			/* All other characters. */
+ 	}
+-	return a;
++	*into=0;	/* and null-terminate. */
+ }
+Index: iperf3-3.0.7/src/cjson.h
+===================================================================
+--- iperf3-3.0.7.orig/src/cjson.h	2020-01-26 16:42:51.509980713 +0100
++++ iperf3-3.0.7/src/cjson.h	2020-01-26 17:13:23.379823445 +0100
+@@ -29,97 +29,122 @@
+ #endif
+ 
+ /* cJSON Types: */
+-#define cJSON_False 0
+-#define cJSON_True 1
+-#define cJSON_NULL 2
+-#define cJSON_Number 3
+-#define cJSON_String 4
+-#define cJSON_Array 5
+-#define cJSON_Object 6
++#define cJSON_False  (1 << 0)
++#define cJSON_True   (1 << 1)
++#define cJSON_NULL   (1 << 2)
++#define cJSON_Number (1 << 3)
++#define cJSON_String (1 << 4)
++#define cJSON_Array  (1 << 5)
++#define cJSON_Object (1 << 6)
+ 	
+ #define cJSON_IsReference 256
++#define cJSON_StringIsConst 512
+ 
+ /* The cJSON structure: */
+ typedef struct cJSON {
+-	struct cJSON *next, *prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
++	struct cJSON *next,*prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ 	struct cJSON *child;		/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ 
+-	int type;			/* The type of the item, as above. */
++	int type;					/* The type of the item, as above. */
+ 
+-	char *valuestring;		/* The item's string, if type==cJSON_String */
+-	int64_t valueint;		/* The item's number, if type==cJSON_Number */
+-	double valuefloat;		/* The item's number, if type==cJSON_Number */
++	char *valuestring;			/* The item's string, if type==cJSON_String */
++	int64_t valueint;			/* The item's number, if type==cJSON_Number */
++	double valuedouble;			/* The item's number, if type==cJSON_Number */
+ 
+-	char *string;			/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
++	char *string;				/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ } cJSON;
+ 
+ typedef struct cJSON_Hooks {
+-      void *(*malloc_fn)(size_t sz );
+-      void (*free_fn)( void *ptr );
++      void *(*malloc_fn)(size_t sz);
++      void (*free_fn)(void *ptr);
+ } cJSON_Hooks;
+ 
+ /* Supply malloc, realloc and free functions to cJSON */
+-extern void cJSON_InitHooks( cJSON_Hooks* hooks );
++extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+ 
+ 
+ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
+-extern cJSON *cJSON_Parse( const char *value );
++extern cJSON *cJSON_Parse(const char *value);
+ /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
+-extern char *cJSON_Print( cJSON *item );
++extern char  *cJSON_Print(cJSON *item);
+ /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
+-extern char *cJSON_PrintUnformatted( cJSON *item );
++extern char  *cJSON_PrintUnformatted(cJSON *item);
++/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
++extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
+ /* Delete a cJSON entity and all subentities. */
+-extern void cJSON_Delete( cJSON *c );
++extern void   cJSON_Delete(cJSON *c);
+ 
+ /* Returns the number of items in an array (or object). */
+-extern int cJSON_GetArraySize( cJSON *array );
++extern int	  cJSON_GetArraySize(cJSON *array);
+ /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+-extern cJSON *cJSON_GetArrayItem( cJSON *array, int item );
++extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
+ /* Get item "string" from object. Case insensitive. */
+-extern cJSON *cJSON_GetObjectItem( cJSON *object, const char *string );
+-
++extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
++extern int cJSON_HasObjectItem(cJSON *object,const char *string);
+ /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+-extern const char *cJSON_GetErrorPtr( void );
++extern const char *cJSON_GetErrorPtr(void);
+ 	
+ /* These calls create a cJSON item of the appropriate type. */
+-extern cJSON *cJSON_CreateNull( void );
+-extern cJSON *cJSON_CreateTrue( void );
+-extern cJSON *cJSON_CreateFalse( void );
+-extern cJSON *cJSON_CreateBool( int b );
+-extern cJSON *cJSON_CreateInt( int64_t num );
+-extern cJSON *cJSON_CreateFloat( double num );
+-extern cJSON *cJSON_CreateString( const char *string );
+-extern cJSON *cJSON_CreateArray( void );
+-extern cJSON *cJSON_CreateObject( void );
++extern cJSON *cJSON_CreateNull(void);
++extern cJSON *cJSON_CreateTrue(void);
++extern cJSON *cJSON_CreateFalse(void);
++extern cJSON *cJSON_CreateBool(int b);
++extern cJSON *cJSON_CreateNumber(double num);
++extern cJSON *cJSON_CreateString(const char *string);
++extern cJSON *cJSON_CreateArray(void);
++extern cJSON *cJSON_CreateObject(void);
+ 
+ /* These utilities create an Array of count items. */
+-extern cJSON *cJSON_CreateIntArray( int64_t *numbers, int count );
+-extern cJSON *cJSON_CreateFloatArray( double *numbers, int count );
+-extern cJSON *cJSON_CreateStringArray( const char **strings, int count );
++extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
++extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
++extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
++extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
+ 
+ /* Append item to the specified array/object. */
+-extern void cJSON_AddItemToArray( cJSON *array, cJSON *item );
+-extern void cJSON_AddItemToObject( cJSON *object, const char *string, cJSON *item );
++extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
++extern void	cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
++extern void	cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item);	/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
+ /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+-extern void cJSON_AddItemReferenceToArray( cJSON *array, cJSON *item );
+-extern void cJSON_AddItemReferenceToObject( cJSON *object, const char *string, cJSON *item );
++extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
++extern void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
+ 
+ /* Remove/Detatch items from Arrays/Objects. */
+-extern cJSON *cJSON_DetachItemFromArray( cJSON *array, int which );
+-extern void cJSON_DeleteItemFromArray( cJSON *array, int which );
+-extern cJSON *cJSON_DetachItemFromObject( cJSON *object, const char *string );
+-extern void cJSON_DeleteItemFromObject( cJSON *object, const char *string );
++extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
++extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
++extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
++extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
+ 	
+ /* Update array items. */
+-extern void cJSON_ReplaceItemInArray( cJSON *array, int which, cJSON *newitem );
+-extern void cJSON_ReplaceItemInObject( cJSON *object, const char *string, cJSON *newitem );
++extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem);	/* Shifts pre-existing items to the right. */
++extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
++extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
++
++/* Duplicate a cJSON item */
++extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
++/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
++need to be released. With recurse!=0, it will duplicate any children connected to the item.
++The item->next and ->prev pointers are always zero on return from Duplicate. */
++
++/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
++/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
++extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
++
++extern void cJSON_Minify(char *json);
++
++/* Macros for creating things quickly. */
++#define cJSON_AddNullToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateNull())
++#define cJSON_AddTrueToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
++#define cJSON_AddFalseToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
++#define cJSON_AddBoolToObject(object,name,b)	cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
++#define cJSON_AddNumberToObject(object,name,n)	cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
++#define cJSON_AddStringToObject(object,name,s)	cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
++
++/* When assigning an integer value, it needs to be propagated to valuedouble too. */
++#define cJSON_SetIntValue(object,val)			((object)?(object)->valueint=(object)->valuedouble=(val):(val))
++#define cJSON_SetNumberValue(object,val)		((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+ 
+-#define cJSON_AddNullToObject( object, name )		cJSON_AddItemToObject( object, name, cJSON_CreateNull() )
+-#define cJSON_AddTrueToObject( object, name )		cJSON_AddItemToObject( object, name, cJSON_CreateTrue() )
+-#define cJSON_AddFalseToObject( object, name )		cJSON_AddItemToObject( object, name, cJSON_CreateFalse() )
+-#define cJSON_AddIntToObject( object, name, n )		cJSON_AddItemToObject( object, name, cJSON_CreateInt( n ) )
+-#define cJSON_AddFloatToObject( object, name, n )	cJSON_AddItemToObject( object, name, cJSON_CreateFloat( n ) )
+-#define cJSON_AddStringToObject( object, name, s )	cJSON_AddItemToObject( object, name, cJSON_CreateString( s ) )
++/* Macro for iterating over an array */
++#define cJSON_ArrayForEach(pos, head)			for(pos = (head)->child; pos != NULL; pos = pos->next)
+ 
+ #ifdef __cplusplus
+ }
+Index: iperf3-3.0.7/src/iperf_util.c
+===================================================================
+--- iperf3-3.0.7.orig/src/iperf_util.c	2020-01-26 16:42:51.509980713 +0100
++++ iperf3-3.0.7/src/iperf_util.c	2020-01-26 17:15:35.784797716 +0100
+@@ -255,10 +255,10 @@
+ 		j = cJSON_CreateBool(va_arg(argp, int));
+ 		break;
+ 		case 'd':
+-		j = cJSON_CreateInt(va_arg(argp, int64_t));
++		j = cJSON_CreateNumber(va_arg(argp, int64_t));
+ 		break;
+ 		case 'f':
+-		j = cJSON_CreateFloat(va_arg(argp, double));
++		j = cJSON_CreateNumber(va_arg(argp, double));
+ 		break;
+ 		case 's':
+ 		j = cJSON_CreateString(va_arg(argp, char *));
+Index: iperf3-3.0.7/src/iperf_api.c
+===================================================================
+--- iperf3-3.0.7.orig/src/iperf_api.c	2020-01-26 16:42:51.509980713 +0100
++++ iperf3-3.0.7/src/iperf_api.c	2020-01-26 17:26:23.281603292 +0100
+@@ -494,11 +494,11 @@
+ 	cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
+         if (test->protocol->id == SOCK_STREAM) {
+ 	    if (test->settings->mss)
+-		cJSON_AddIntToObject(test->json_start, "tcp_mss", test->settings->mss);
++		cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
+ 	    else {
+ 		len = sizeof(opt);
+ 		getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
+-		cJSON_AddIntToObject(test->json_start, "tcp_mss_default", opt);
++		cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", opt);
+ 	    }
+ 	}
+     } else if (test->verbose) {
+@@ -1092,40 +1092,40 @@
+ 	    cJSON_AddTrueToObject(j, "tcp");
+ 	else if (test->protocol->id == Pudp)
+ 	    cJSON_AddTrueToObject(j, "udp");
+-	cJSON_AddIntToObject(j, "omit", test->omit);
++	cJSON_AddNumberToObject(j, "omit", test->omit);
+ 	if (test->server_affinity != -1)
+-	    cJSON_AddIntToObject(j, "server_affinity", test->server_affinity);
++	    cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
+ 	if (test->duration)
+-	    cJSON_AddIntToObject(j, "time", test->duration);
++	    cJSON_AddNumberToObject(j, "time", test->duration);
+ 	if (test->settings->bytes)
+-	    cJSON_AddIntToObject(j, "num", test->settings->bytes);
++	    cJSON_AddNumberToObject(j, "num", test->settings->bytes);
+ 	if (test->settings->blocks)
+-	    cJSON_AddIntToObject(j, "blockcount", test->settings->blocks);
++	    cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
+ 	if (test->settings->mss)
+-	    cJSON_AddIntToObject(j, "MSS", test->settings->mss);
++	    cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
+ 	if (test->no_delay)
+ 	    cJSON_AddTrueToObject(j, "nodelay");
+-	cJSON_AddIntToObject(j, "parallel", test->num_streams);
++	cJSON_AddNumberToObject(j, "parallel", test->num_streams);
+ 	if (test->reverse)
+ 	    cJSON_AddTrueToObject(j, "reverse");
+ 	if (test->settings->socket_bufsize)
+-	    cJSON_AddIntToObject(j, "window", test->settings->socket_bufsize);
++	    cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
+ 	if (test->settings->blksize)
+-	    cJSON_AddIntToObject(j, "len", test->settings->blksize);
++	    cJSON_AddNumberToObject(j, "len", test->settings->blksize);
+ 	if (test->settings->rate)
+-	    cJSON_AddIntToObject(j, "bandwidth", test->settings->rate);
++	    cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
+ 	if (test->settings->burst)
+-	    cJSON_AddIntToObject(j, "burst", test->settings->burst);
++	    cJSON_AddNumberToObject(j, "burst", test->settings->burst);
+ 	if (test->settings->tos)
+-	    cJSON_AddIntToObject(j, "TOS", test->settings->tos);
++	    cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
+ 	if (test->settings->flowlabel)
+-	    cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel);
++	    cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
+ 	if (test->title)
+ 	    cJSON_AddStringToObject(j, "title", test->title);
+ 	if (test->congestion)
+ 	    cJSON_AddStringToObject(j, "congestion", test->congestion);
+ 	if (test->get_server_output)
+-	    cJSON_AddIntToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
++	    cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
+ 
+ 	if (test->debug) {
+ 	    printf("send_parameters:\n%s\n", cJSON_Print(j));
+@@ -1224,14 +1224,14 @@
+ 	i_errno = IEPACKAGERESULTS;
+ 	r = -1;
+     } else {
+-	cJSON_AddFloatToObject(j, "cpu_util_total", test->cpu_util[0]);
+-	cJSON_AddFloatToObject(j, "cpu_util_user", test->cpu_util[1]);
+-	cJSON_AddFloatToObject(j, "cpu_util_system", test->cpu_util[2]);
++	cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
++	cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
++	cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
+ 	if ( ! test->sender )
+ 	    sender_has_retransmits = -1;
+ 	else
+ 	    sender_has_retransmits = test->sender_has_retransmits;
+-	cJSON_AddIntToObject(j, "sender_has_retransmits", sender_has_retransmits);
++	cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
+ 
+ 	/* If on the server and sending server output, then do this */
+ 	if (test->role == 's' && test->get_server_output) {
+@@ -1275,12 +1275,12 @@
+ 		    cJSON_AddItemToArray(j_streams, j_stream);
+ 		    bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received;
+ 		    retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
+-		    cJSON_AddIntToObject(j_stream, "id", sp->id);
+-		    cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred);
+-		    cJSON_AddIntToObject(j_stream, "retransmits", retransmits);
+-		    cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter);
+-		    cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error);
+-		    cJSON_AddIntToObject(j_stream, "packets", sp->packet_count);
++		    cJSON_AddNumberToObject(j_stream, "id", sp->id);
++		    cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
++		    cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
++		    cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
++		    cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
++		    cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
+ 		}
+ 	    }
+ 	    if (r == 0 && test->debug) {
+@@ -1341,9 +1341,9 @@
+ 		printf("get_results\n%s\n", cJSON_Print(j));
+ 	    }
+ 
+-	    test->remote_cpu_util[0] = j_cpu_util_total->valuefloat;
+-	    test->remote_cpu_util[1] = j_cpu_util_user->valuefloat;
+-	    test->remote_cpu_util[2] = j_cpu_util_system->valuefloat;
++	    test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
++	    test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
++	    test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
+ 	    result_has_retransmits = j_sender_has_retransmits->valueint;
+ 	    if (! test->sender)
+ 		test->sender_has_retransmits = result_has_retransmits;
+@@ -1372,7 +1372,7 @@
+ 			    sid = j_id->valueint;
+ 			    bytes_transferred = j_bytes->valueint;
+ 			    retransmits = j_retransmits->valueint;
+-			    jitter = j_jitter->valuefloat;
++			    jitter = j_jitter->valuedouble;
+ 			    cerror = j_errors->valueint;
+ 			    pcount = j_packets->valueint;
+ 			    SLIST_FOREACH(sp, &test->streams, streams)
diff -Nru iperf3-3.0.7/debian/patches/series iperf3-3.0.7/debian/patches/series
--- iperf3-3.0.7/debian/patches/series	2014-06-21 18:07:34.000000000 +0200
+++ iperf3-3.0.7/debian/patches/series	2020-01-26 16:44:10.000000000 +0100
@@ -1 +1,2 @@
 001-manpages
+002-CVE-2016-4303
diff -Nru iperf3-3.0.7/debian/rules iperf3-3.0.7/debian/rules
--- iperf3-3.0.7/debian/rules	2014-09-11 11:09:04.000000000 +0200
+++ iperf3-3.0.7/debian/rules	2020-01-26 18:06:37.000000000 +0100
@@ -6,4 +6,4 @@
 	dh_installchangelogs RELEASE_NOTES
 
 %:
-	dh $@ --with autotools-dev
+	dh $@ --with autotools-dev --with autoreconf
