#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)
++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;
char name[MAXHOSTNAMELEN];
int have_v6_break = 0, in_v6_break = 0;
- *subarray = NULL;
+ 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;
}
switch (type) {
case DNS_T_A:
- add_assoc_string(*subarray, "type", "A", 1);
+ 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, 1);
+ add_assoc_string(subarray, "ip", name);
cp += dlen;
break;
case DNS_T_MX:
- add_assoc_string(*subarray, "type", "MX", 1);
+ CHECKCP(2);
+ add_assoc_string(subarray, "type", "MX");
GETSHORT(n, cp);
- add_assoc_long(*subarray, "pri", n);
+ add_assoc_long(subarray, "pri", n);
/* no break; */
case DNS_T_CNAME:
if (type == DNS_T_CNAME) {
/* no break; */
case DNS_T_PTR:
if (type == DNS_T_PTR) {
- add_assoc_string(*subarray, "type", "PTR", 1);
+ 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;
}
break;
case DNS_T_HINFO:
/* See RFC 1010 for values */
- add_assoc_string(*subarray, "type", "HINFO", 1);
+ add_assoc_string(subarray, "type", "HINFO");
+ CHECKCP(1);
n = *cp & 0xFF;
cp++;
- add_assoc_stringl(*subarray, "cpu", (char*)cp, n, 1);
+ CHECKCP(n);
+ add_assoc_stringl(subarray, "cpu", (char*)cp, n);
cp += n;
+ CHECKCP(1);
n = *cp & 0xFF;
cp++;
- add_assoc_stringl(*subarray, "os", (char*)cp, n, 1);
+ 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 = NULL;
+ zval entries;
+ zend_string *tp;
- add_assoc_string(*subarray, "type", "TXT", 1);
- tp = emalloc(dlen + 1);
+ add_assoc_string(subarray, "type", "TXT");
+ tp = STR_ALLOC(dlen, 0);
- MAKE_STD_ZVAL(entries);
- array_init(entries);
+ 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 + l2 , cp + l1 + 1, n);
++ memcpy(tp->val + l2 , cp + l1 + 1, n);
+ add_next_index_stringl(entries, cp + l1 + 1, n, 1);
}
- 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[l2] = '\0';
++ tp->val[l2] = '\0';
++ tp->len = l2;
cp += dlen;
- add_assoc_stringl(*subarray, "txt", tp, l2, 0);
- add_assoc_zval(*subarray, "entries", entries);
+ add_assoc_str(subarray, "txt", tp);
+ add_assoc_zval(subarray, "entries", &entries);
}
break;
case DNS_T_SOA:
- add_assoc_string(*subarray, "type", "SOA", 1);
+ 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, 1);
+ 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, 1);
+ add_assoc_string(subarray, "rname", name);
+ CHECKCP(5*4);
GETLONG(n, cp);
- add_assoc_long(*subarray, "serial", n);
+ add_assoc_long(subarray, "serial", n);
GETLONG(n, cp);
- add_assoc_long(*subarray, "refresh", n);
+ add_assoc_long(subarray, "refresh", n);
GETLONG(n, cp);
- add_assoc_long(*subarray, "retry", n);
+ add_assoc_long(subarray, "retry", n);
GETLONG(n, cp);
- add_assoc_long(*subarray, "expire", n);
+ add_assoc_long(subarray, "expire", n);
GETLONG(n, cp);
- add_assoc_long(*subarray, "minimum-ttl", n);
+ add_assoc_long(subarray, "minimum-ttl", n);
break;
case DNS_T_AAAA:
tp = (u_char*)name;
break;
case DNS_T_A6:
p = cp;
- add_assoc_string(*subarray, "type", "A6", 1);
+ add_assoc_string(subarray, "type", "A6");
+ CHECKCP(1);
n = ((int)cp[0]) & 0xFF;
cp++;
- add_assoc_long(*subarray, "masklen", n);
+ add_assoc_long(subarray, "masklen", n);
tp = (u_char*)name;
if (n > 15) {
have_v6_break = 1;
tp++;
}
tp[0] = '\0';
- add_assoc_string(*subarray, "ipv6", name, 1);
+ 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;
}
}
break;
case DNS_T_SRV:
- add_assoc_string(*subarray, "type", "SRV", 1);
+ CHECKCP(3*2);
+ add_assoc_string(subarray, "type", "SRV");
GETSHORT(n, cp);
- add_assoc_long(*subarray, "pri", n);
+ add_assoc_long(subarray, "pri", n);
GETSHORT(n, cp);
- add_assoc_long(*subarray, "weight", n);
+ add_assoc_long(subarray, "weight", n);
GETSHORT(n, cp);
- add_assoc_long(*subarray, "port", n);
+ add_assoc_long(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;
}
cp += n;
- add_assoc_string(*subarray, "target", name, 1);
+ add_assoc_string(subarray, "target", name);
break;
case DNS_T_NAPTR:
- add_assoc_string(*subarray, "type", "NAPTR", 1);
+ CHECKCP(2*2);
+ add_assoc_string(subarray, "type", "NAPTR");
GETSHORT(n, cp);
- add_assoc_long(*subarray, "order", n);
+ add_assoc_long(subarray, "order", n);
GETSHORT(n, cp);
- add_assoc_long(*subarray, "pref", n);
+ add_assoc_long(subarray, "pref", n);
+
+ CHECKCP(1);
n = (cp[0] & 0xFF);
- cp++;
+ CHECKCP(n);
- add_assoc_stringl(*subarray, "flags", (char*)cp, n, 1);
+ 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, 1);
++ 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, 1);
++ 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;
}
/* YAY! Our real answers! */
while (an-- && cp && cp < end) {
- zval *retval;
+ 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 (retval != NULL && store_results) {
- add_next_index_zval(return_value, retval);
+ if (Z_TYPE(retval) != IS_UNDEF && store_results) {
+ add_next_index_zval(return_value, &retval);
}
}
* Process when only requesting addtl so that we can skip through the section
*/
while (ns-- > 0 && cp && cp < end) {
- zval *retval = NULL;
+ 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 (retval != NULL) {
- add_next_index_zval(authns, retval);
+ if (Z_TYPE(retval) != IS_UNDEF) {
+ add_next_index_zval(authns, &retval);
}
}
}
if (addtl) {
/* Additional records associated with authoritative name servers */
while (ar-- > 0 && cp && cp < end) {
- zval *retval = NULL;
+ 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 (retval != NULL) {
- add_next_index_zval(addtl, retval);
+ if (Z_TYPE(retval) != IS_UNDEF) {
+ add_next_index_zval(addtl, &retval);
}
}
}