components/php-5_2/php-sapi/patches/64_php_19556437.patch
branchs11-update
changeset 3777 68aef260e079
equal deleted inserted replaced
3773:2cdfec77a8eb 3777:68aef260e079
       
     1 Fix for CVE-2014-3597
       
     2 Patch:
       
     3 http://git.php.net/?p=php-src.git;a=commitdiff;h=2fefae47716d501aec41c1102f3fd4531f070b05
       
     4 This patch was created by hand from the above community diff.
       
     5 
       
     6 
       
     7 --- php-5.2.17/ext/standard/dns.c_orig	2014-10-29 09:08:05.187565521 -0700
       
     8 +++ php-5.2.17/ext/standard/dns.c	2014-11-04 10:54:59.065340474 -0800
       
     9 @@ -396,8 +396,14 @@
       
    10  #define php_dns_free_res(__res__)
       
    11  #endif
       
    12  
       
    13 +#define CHECKCP(n) do { \
       
    14 +	if (cp + n > end) { \
       
    15 +		return NULL; \
       
    16 +	} \
       
    17 +} while (0)
       
    18 +
       
    19  /* {{{ php_parserr */
       
    20 -static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray)
       
    21 +static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, zval **subarray)
       
    22  {
       
    23  	u_short type, class, dlen;
       
    24  	u_long ttl;
       
    25 @@ -409,16 +415,18 @@
       
    26  
       
    27  	*subarray = NULL;
       
    28  
       
    29 -	n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
       
    30 +	n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2);
       
    31  	if (n < 0) {
       
    32  		return NULL;
       
    33  	}
       
    34  	cp += n;
       
    35  	
       
    36 +	CHECKCP(10);
       
    37  	GETSHORT(type, cp);
       
    38  	GETSHORT(class, cp);
       
    39  	GETLONG(ttl, cp);
       
    40  	GETSHORT(dlen, cp);
       
    41 +	CHECKCP(dlen);
       
    42  	if (type_to_fetch != T_ANY && type != type_to_fetch) {
       
    43  		cp += dlen;
       
    44  		return cp;
       
    45 @@ -435,12 +443,14 @@
       
    46  	add_assoc_string(*subarray, "host", name, 1);
       
    47  	switch (type) {
       
    48  		case DNS_T_A:
       
    49 +			CHECKCP(4);
       
    50  			add_assoc_string(*subarray, "type", "A", 1);
       
    51  			snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
       
    52  			add_assoc_string(*subarray, "ip", name, 1);
       
    53  			cp += dlen;
       
    54  			break;
       
    55  		case DNS_T_MX:
       
    56 +			CHECKCP(2);
       
    57  			add_assoc_string(*subarray, "type", "MX", 1);
       
    58  			GETSHORT(n, cp);
       
    59  			add_assoc_long(*subarray, "pri", n);
       
    60 @@ -456,7 +466,7 @@
       
    61  		case DNS_T_PTR:
       
    62  			if (type == DNS_T_PTR)
       
    63  				add_assoc_string(*subarray, "type", "PTR", 1);
       
    64 -			n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
       
    65 +			n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
       
    66  			if (n < 0) {
       
    67  				return NULL;
       
    68  			}
       
    69 @@ -466,51 +476,59 @@
       
    70  		case DNS_T_HINFO:
       
    71  			/* See RFC 1010 for values */
       
    72  			add_assoc_string(*subarray, "type", "HINFO", 1);
       
    73 +			CHECKCP(1);
       
    74  			n = *cp & 0xFF;
       
    75  			cp++;
       
    76 +			CHECKCP(n);
       
    77  			add_assoc_stringl(*subarray, "cpu", cp, n, 1);
       
    78  			cp += n;
       
    79 +			CHECKCP(1);
       
    80  			n = *cp & 0xFF;
       
    81  			cp++;
       
    82 +			CHECKCP(n);
       
    83  			add_assoc_stringl(*subarray, "os", cp, n, 1);
       
    84  			cp += n;
       
    85  			break;
       
    86  		case DNS_T_TXT: 
       
    87  			{
       
    88 -				int ll = 0;
       
    89 +				int l1 = 0, l2 = 0;
       
    90  
       
    91  				add_assoc_string(*subarray, "type", "TXT", 1);
       
    92  				tp = emalloc(dlen + 1);
       
    93  				
       
    94 -				while (ll < dlen) {
       
    95 -					n = cp[ll];
       
    96 -					if ((ll + n) >= dlen) {
       
    97 +				while (l1 < dlen) {
       
    98 +					n = cp[l1];
       
    99 +					if ((l1 + n) >= dlen) {
       
   100  						    // Invalid chunk length, truncate
       
   101 -							n = dlen - (ll + 1);
       
   102 +							n = dlen - (l1 + 1);
       
   103  				    }
       
   104 -					memcpy(tp + ll , cp + ll + 1, n);
       
   105 -					ll = ll + n + 1;
       
   106 +					if (n) {
       
   107 +						memcpy(tp + l2 , cp + l1 + 1, n);
       
   108 +					}
       
   109 +					l1 = l1 + n + 1;
       
   110 +					l2 = l2 + n;
       
   111  				}
       
   112 -				tp[dlen] = '\0';
       
   113 +				tp[l2] = '\0';
       
   114  				cp += dlen;
       
   115  
       
   116 -				add_assoc_stringl(*subarray, "txt", tp, dlen - 1, 0);
       
   117 +				add_assoc_stringl(*subarray, "txt", tp, l2, 0);
       
   118  			}
       
   119  			break;
       
   120  		case DNS_T_SOA:
       
   121  			add_assoc_string(*subarray, "type", "SOA", 1);
       
   122 -			n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
       
   123 +			n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
       
   124  			if (n < 0) {
       
   125  				return NULL;
       
   126  			}
       
   127  			cp += n;
       
   128  			add_assoc_string(*subarray, "mname", name, 1);
       
   129 -			n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
       
   130 +			n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
       
   131  			if (n < 0) {
       
   132  				return NULL;
       
   133  			}
       
   134  			cp += n;
       
   135  			add_assoc_string(*subarray, "rname", name, 1);
       
   136 +			CHECKCP(5*4);
       
   137  			GETLONG(n, cp);
       
   138  			add_assoc_long(*subarray, "serial", n);
       
   139  			GETLONG(n, cp);
       
   140 @@ -524,6 +542,7 @@
       
   141  			break;
       
   142  		case DNS_T_AAAA:
       
   143  			tp = name;
       
   144 +			CHECKCP(8*2);
       
   145  			for(i=0; i < 8; i++) {
       
   146  				GETSHORT(s, cp);
       
   147  				if (s != 0) {
       
   148 @@ -558,6 +577,7 @@
       
   149  		case DNS_T_A6:
       
   150  			p = cp;
       
   151  			add_assoc_string(*subarray, "type", "A6", 1);
       
   152 +			CHECKCP(1);
       
   153  			n = ((int)cp[0]) & 0xFF;
       
   154  			cp++;
       
   155  			add_assoc_long(*subarray, "masklen", n);
       
   156 @@ -593,6 +613,7 @@
       
   157  				cp++;
       
   158  			}
       
   159  			for(i = (n+8)/16; i < 8; i++) {
       
   160 +				CHECKCP(2);
       
   161  				GETSHORT(s, cp);
       
   162  				if (s != 0) {
       
   163  					if (tp > (u_char *)name) {
       
   164 @@ -622,7 +643,7 @@
       
   165  			tp[0] = '\0';
       
   166  			add_assoc_string(*subarray, "ipv6", name, 1);
       
   167  			if (cp < p + dlen) {
       
   168 -				n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
       
   169 +				n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
       
   170  				if (n < 0) {
       
   171  					return NULL;
       
   172  				}
       
   173 @@ -631,6 +652,7 @@
       
   174  			}
       
   175  			break;
       
   176  		case DNS_T_SRV:
       
   177 +			CHECKCP(3*2);
       
   178  			add_assoc_string(*subarray, "type", "SRV", 1);
       
   179  			GETSHORT(n, cp);
       
   180  			add_assoc_long(*subarray, "pri", n);
       
   181 @@ -638,7 +660,7 @@
       
   182  			add_assoc_long(*subarray, "weight", n);
       
   183  			GETSHORT(n, cp);
       
   184  			add_assoc_long(*subarray, "port", n);
       
   185 -			n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
       
   186 +			n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
       
   187  			if (n < 0) {
       
   188  				return NULL;
       
   189  			}
       
   190 @@ -646,21 +668,34 @@
       
   191  			add_assoc_string(*subarray, "target", name, 1);
       
   192  			break;
       
   193  		case DNS_T_NAPTR:
       
   194 +			CHECKCP(2*2);
       
   195  			add_assoc_string(*subarray, "type", "NAPTR", 1);
       
   196  			GETSHORT(n, cp);
       
   197  			add_assoc_long(*subarray, "order", n);
       
   198  			GETSHORT(n, cp);
       
   199  			add_assoc_long(*subarray, "pref", n);
       
   200 +
       
   201 +			CHECKCP(1);
       
   202  			n = (cp[0] & 0xFF);
       
   203 -			add_assoc_stringl(*subarray, "flags", ++cp, n, 1);
       
   204 +			cp++;
       
   205 +			CHECKCP(n);
       
   206 +			add_assoc_stringl(*subarray, "flags", cp, n, 1);
       
   207  			cp += n;
       
   208 +
       
   209 +			CHECKCP(1);
       
   210  			n = (cp[0] & 0xFF);
       
   211 -			add_assoc_stringl(*subarray, "services", ++cp, n, 1);
       
   212 +			cp++;
       
   213 +			CHECKCP(n);
       
   214 +			add_assoc_stringl(*subarray, "services", cp, n, 1);
       
   215  			cp += n;
       
   216 +
       
   217 +			CHECKCP(1);
       
   218  			n = (cp[0] & 0xFF);
       
   219 -			add_assoc_stringl(*subarray, "regex", ++cp, n, 1);
       
   220 +			cp++;
       
   221 +			CHECKCP(n);
       
   222 +			add_assoc_stringl(*subarray, "regex", cp, n, 1);
       
   223  			cp += n;
       
   224 -			n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
       
   225 +			n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
       
   226  			if (n < 0) {
       
   227  				return NULL;
       
   228  			}
       
   229 @@ -833,7 +868,7 @@
       
   230  			while (an-- && cp && cp < end) {
       
   231  				zval *retval;
       
   232  
       
   233 -				cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval);
       
   234 +				cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, &retval);
       
   235  				if (retval != NULL && store_results) {
       
   236  					add_next_index_zval(return_value, retval);
       
   237  				}
       
   238 @@ -848,7 +883,7 @@
       
   239  		while (ns-- > 0 && cp && cp < end) {
       
   240  			zval *retval;
       
   241  
       
   242 -			cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
       
   243 +			cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, &retval);
       
   244  			if (retval != NULL) {
       
   245  				add_next_index_zval(authns, retval);
       
   246  			}
       
   247 @@ -857,7 +892,7 @@
       
   248  		while (ar-- > 0 && cp && cp < end) {
       
   249  			zval *retval;
       
   250  
       
   251 -			cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
       
   252 +			cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, &retval);
       
   253  			if (retval != NULL) {
       
   254  				add_next_index_zval(addtl, retval);
       
   255  			}