[php-src] PR #25282: ext/standard/dns.c: drop partially built records in php_parserr()
| From: | Marti2203 | Date: | Sat, 07 Nov 2026 14:24:47 +0000 |
| Subject: | [php-src] PR #25282: ext/standard/dns.c: drop partially built records in php_parserr() | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-40392@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/25282
Author: Marti2203
php_parserr() creates the record array and adds host, class
and ttl before it parses the type-specific data. If that parse fails (a
CHECKCP() bound check, a failing dn_expand(), or the CAA length check), it
returns NULL but leaves the populated array in subarray. The callers in
PHP_FUNCTION(dns_get_record) only test Z_TYPE(retval) != IS_UNDEF, so the
incomplete array is appended to the result (or to $authns / $addtl) before
the NULL ends the loop.
For a response whose last answer is malformed:
- MX/CNAME/NS/PTR/SRV with a bad compression pointer in the target name: the record has
type (and pri for MX) but no target.
- An A record with rdlength < 4 at the end of the message: the record has only
host, class and ttl.
- SOA, A6, NAPTR and CAA follow the same pattern.
This change destroys the array on every failure path, as default: already does for
unknown types (zval_ptr_dtor(subarray); ZVAL_UNDEF(subarray);). subarray
is set to UNDEF at the start of php_parserr(), so the early failures before
array_init() are unaffected.
There is no memory-safety issue; the impact is low: a resolver or authoritative server sending a
malformed response can make dns_get_record() return entries with missing
type/target/ip keys.
Tested with an LD_PRELOAD shim that replaces res_nsearch() with canned
responses (one good A record followed by an MX whose target is the compression pointer
0xc0ff; an A record with rdlength 2; a CNAME with a bad pointer):
```
before: [{"type":"A","ip":"192.0.2.1",...},
{"host":"example.test","class":"IN","ttl":3600,"type":"MX","pri":10}]
after: [{"type":"A","ip":"192.0.2.1",...}]
```
No .phpt is included: it would need a resolver mock, which the test suite doesn't
have (GH-23798 left out a test for the same reason).
Related: GH-22201 (missing CHECKCP in the A6 branch); with this change that check also
drops the partial record. GH-17919 is about dns_get_record() error reporting in
general.
This was found while following up cases from an LLM-Enhanced Static Analysis Engine and verified
manually.