diff options
author | Anatol Belski <ab@php.net> | 2014-08-19 09:58:35 +0200 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-08-19 09:58:35 +0200 |
commit | 5dc4f44f3e37a4f2f818ec26891882b427af14a0 (patch) | |
tree | 497641926d2efa95278bae20010fa25bab024979 | |
parent | 30e0aa5b6b01d206326671e87d5ca6f21aa13fdd (diff) | |
parent | 6070757c77a226fecce5f2d029084cf68c979762 (diff) | |
download | php-git-5dc4f44f3e37a4f2f818ec26891882b427af14a0.tar.gz |
Merge remote-tracking branch 'php/master'
Conflicts:
ext/standard/dns.c
-rw-r--r-- | ext/standard/dns.c | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/ext/standard/dns.c b/ext/standard/dns.c index c760fc0713..3ad926820d 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -411,8 +411,14 @@ PHP_FUNCTION(dns_check_record) #if HAVE_FULL_DNS_FUNCS +#define CHECKCP(n) do { \ + if (cp + n > end) { \ + return NULL; \ + } \ +} while (0) + /* {{{ php_parserr */ -static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, int raw, zval *subarray) +static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, int raw, zval *subarray) { u_short type, class, dlen; u_long ttl; @@ -424,16 +430,18 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int ZVAL_UNDEF(subarray); - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2); + n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2); if (n < 0) { return NULL; } cp += n; + CHECKCP(10); GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); GETSHORT(dlen, cp); + CHECKCP(dlen); if (type_to_fetch != T_ANY && type != type_to_fetch) { cp += dlen; return cp; @@ -459,12 +467,14 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int switch (type) { case DNS_T_A: + CHECKCP(4); add_assoc_string(subarray, "type", "A"); snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); add_assoc_string(subarray, "ip", name); cp += dlen; break; case DNS_T_MX: + CHECKCP(2); add_assoc_string(subarray, "type", "MX"); GETSHORT(n, cp); add_assoc_int(subarray, "pri", n); @@ -483,7 +493,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int if (type == DNS_T_PTR) { add_assoc_string(subarray, "type", "PTR"); } - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); if (n < 0) { return NULL; } @@ -493,18 +503,22 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int case DNS_T_HINFO: /* See RFC 1010 for values */ add_assoc_string(subarray, "type", "HINFO"); + CHECKCP(1); n = *cp & 0xFF; cp++; + CHECKCP(n); add_assoc_stringl(subarray, "cpu", (char*)cp, n); cp += n; + CHECKCP(1); n = *cp & 0xFF; cp++; + CHECKCP(n); add_assoc_stringl(subarray, "os", (char*)cp, n); cp += n; break; case DNS_T_TXT: { - int ll = 0; + int l1 = 0, l2 = 0; zval entries; zend_string *tp; @@ -513,18 +527,21 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int array_init(&entries); - while (ll < dlen) { - n = cp[ll]; - if ((ll + n) >= dlen) { + while (l1 < dlen) { + n = cp[l1]; + if ((l1 + n) >= dlen) { // Invalid chunk length, truncate - n = dlen - (ll + 1); + n = dlen - (l1 + 1); + } + if (n) { + memcpy(tp->val + l2 , cp + l1 + 1, n); + add_next_index_stringl(&entries, cp + l1 + 1, n); } - memcpy(tp->val + ll , cp + ll + 1, n); - add_next_index_stringl(&entries, (char*)cp + ll + 1, n); - ll = ll + n + 1; + l1 = l1 + n + 1; + l2 = l2 + n; } - tp->val[dlen] = '\0'; - tp->len = dlen; + tp->val[l2] = '\0'; + tp->len = l2; cp += dlen; add_assoc_str(subarray, "txt", tp); @@ -533,18 +550,19 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int break; case DNS_T_SOA: add_assoc_string(subarray, "type", "SOA"); - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); if (n < 0) { return NULL; } cp += n; add_assoc_string(subarray, "mname", name); - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); if (n < 0) { return NULL; } cp += n; add_assoc_string(subarray, "rname", name); + CHECKCP(5*4); GETLONG(n, cp); add_assoc_int(subarray, "serial", n); GETLONG(n, cp); @@ -558,6 +576,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int break; case DNS_T_AAAA: tp = (u_char*)name; + CHECKCP(8*2); for(i=0; i < 8; i++) { GETSHORT(s, cp); if (s != 0) { @@ -592,6 +611,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int case DNS_T_A6: p = cp; add_assoc_string(subarray, "type", "A6"); + CHECKCP(1); n = ((int)cp[0]) & 0xFF; cp++; add_assoc_int(subarray, "masklen", n); @@ -627,6 +647,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int cp++; } for (i = (n + 8) / 16; i < 8; i++) { + CHECKCP(2); GETSHORT(s, cp); if (s != 0) { if (tp > (u_char *)name) { @@ -656,7 +677,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int tp[0] = '\0'; add_assoc_string(subarray, "ipv6", name); if (cp < p + dlen) { - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); if (n < 0) { return NULL; } @@ -665,6 +686,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int } break; case DNS_T_SRV: + CHECKCP(3*2); add_assoc_string(subarray, "type", "SRV"); GETSHORT(n, cp); add_assoc_int(subarray, "pri", n); @@ -672,7 +694,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int add_assoc_int(subarray, "weight", n); GETSHORT(n, cp); add_assoc_int(subarray, "port", n); - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); if (n < 0) { return NULL; } @@ -680,21 +702,35 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int add_assoc_string(subarray, "target", name); break; case DNS_T_NAPTR: + CHECKCP(2*2); add_assoc_string(subarray, "type", "NAPTR"); GETSHORT(n, cp); add_assoc_int(subarray, "order", n); GETSHORT(n, cp); add_assoc_int(subarray, "pref", n); + + CHECKCP(1); n = (cp[0] & 0xFF); - add_assoc_stringl(subarray, "flags", (char*)++cp, n); + cp++; + CHECKCP(n); + add_assoc_stringl(subarray, "flags", (char*)cp, n); cp += n; + + CHECKCP(1); n = (cp[0] & 0xFF); - add_assoc_stringl(subarray, "services", (char*)++cp, n); + cp++; + CHECKCP(n); + add_assoc_stringl(subarray, "services", (char*)cp, n); cp += n; + + CHECKCP(1); n = (cp[0] & 0xFF); - add_assoc_stringl(subarray, "regex", (char*)++cp, n); + cp++; + CHECKCP(n); + add_assoc_stringl(subarray, "regex", (char*)cp, n); cp += n; - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); + + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); if (n < 0) { return NULL; } @@ -887,7 +923,7 @@ PHP_FUNCTION(dns_get_record) while (an-- && cp && cp < end) { zval retval; - cp = php_parserr(cp, &answer, type_to_fetch, store_results, raw, &retval); + cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, raw, &retval); if (Z_TYPE(retval) != IS_UNDEF && store_results) { add_next_index_zval(return_value, &retval); } @@ -900,7 +936,7 @@ PHP_FUNCTION(dns_get_record) while (ns-- > 0 && cp && cp < end) { zval retval; - cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, raw, &retval); + cp = php_parserr(cp, end, &answer, DNS_T_ANY, authns != NULL, raw, &retval); if (Z_TYPE(retval) != IS_UNDEF) { add_next_index_zval(authns, &retval); } @@ -912,7 +948,7 @@ PHP_FUNCTION(dns_get_record) while (ar-- > 0 && cp && cp < end) { zval retval; - cp = php_parserr(cp, &answer, DNS_T_ANY, 1, raw, &retval); + cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, raw, &retval); if (Z_TYPE(retval) != IS_UNDEF) { add_next_index_zval(addtl, &retval); } |