Skip to content

fix several latent bugs across parsing, OOM handling, and option validation#234

Open
vixie wants to merge 2 commits into
masterfrom
initial_claude_zed
Open

fix several latent bugs across parsing, OOM handling, and option validation#234
vixie wants to merge 2 commits into
masterfrom
initial_claude_zed

Conversation

@vixie

@vixie vixie commented May 9, 2026

Copy link
Copy Markdown
Collaborator

(from claude via zed.)

asinfo.c: inet_pton() returns 0 (not -1) on malformed addresses; the old check let bogus rdata through with an uninitialized stack buffer. Also use the canonical h_errno for the existence probe and propagate res_ninit() failure instead of charging ahead.

dnsdbq.c: -O case in qparam_option() referred to optarg instead of its own arg parameter; harmless today but a footgun. wordexp() return is now checked before dereferencing we_wordv. Reject -p minimal -J at parse time -- ruminate_json() builds a query without a mode, which previously tripped abort() inside present_minimal_lookup().

netio.c: realloc() / asprintf() failure no longer slides into a NULL deref. The earlier asprintf cast turned a -1 return into SIZE_MAX and the realloc results were unchecked. Also handle fdopen() failure on the sort pipes.

pdns.c: tuple_make() now requires rrname/rrtype/rdata up front, instead of leaving NULL pointers for sortable_rdatum() and the sort-key fprintf() to dereference on malformed records.

time.c: avoid imaxabs(INTMAX_MIN) UB in the relative-time path.

tokstr.h: drop a duplicate prototype.

…dation

asinfo.c: inet_pton() returns 0 (not -1) on malformed addresses; the old
check let bogus rdata through with an uninitialized stack buffer. Also
use the canonical h_errno for the existence probe and propagate
res_ninit() failure instead of charging ahead.

dnsdbq.c: -O case in qparam_option() referred to optarg instead of its
own arg parameter; harmless today but a footgun. wordexp() return is now
checked before dereferencing we_wordv. Reject -p minimal -J at parse
time -- ruminate_json() builds a query without a mode, which previously
tripped abort() inside present_minimal_lookup().

netio.c: realloc() / asprintf() failure no longer slides into a NULL
deref. The earlier asprintf cast turned a -1 return into SIZE_MAX and
the realloc results were unchecked. Also handle fdopen() failure on the
sort pipes.

pdns.c: tuple_make() now requires rrname/rrtype/rdata up front, instead
of leaving NULL pointers for sortable_rdatum() and the sort-key
fprintf() to dereference on malformed records.

time.c: avoid imaxabs(INTMAX_MIN) UB in the relative-time path.

tokstr.h: drop a duplicate prototype.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cmikk cmikk self-requested a review June 9, 2026 21:46

@cmikk cmikk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting a few mostly style / consistency changes, plus clarification that the MAX_FETCH_BUF limit is sufficient for a properly operating supported pDNS API server, rather than a tunable (like MAX_FETCHES could be).

Comment thread netio.c
writer_t writer = query->writer;
qparam_ct qp = &query->qp;
size_t bytes = size * nmemb;
char *x;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable should be factored out. Where it is used, a more straightforward:

final->buf = realloc(....);
if (final->buf == NULL)
     my_panic(true, "realloc");

would be clearer.

Comment thread netio.c
assert(writer->ps_buf == NULL && writer->ps_len == 0);
writer->ps_len = (size_t)
asprintf(&writer->ps_buf, "-- %s (%s)\n",
int x = asprintf(&writer->ps_buf, "-- %s (%s)\n",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're retaining the return value of asprintf here in writer->ps_len, I would suggest giving it a different name from x, which is used elsewhere in this code base for a "throwaway after check" return value. In asinfo.c, for example, int n = asprintf(...) is used for this purpose.

Comment thread netio.c

fetch->buf = realloc(fetch->buf, fetch->len + bytes);
if (fetch->len + bytes > MAX_FETCH_BUF) {
printf("?? very large response\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failure of this check should:

  1. use my_logf() to print a warning rather than printf()ing to the output, and:
  2. return CURL_WRITEFUNC_ERROR, since returning 0 to signal error is not robust.

Comment thread defs.h
* must not be greater than any pDNS system's concurrent connection limit.
*/
#define MAX_FETCHES 8
#define MAX_FETCH_BUF (16*1024*1024)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not immediately clear from context whether this is a tunable resource limit or a "sanity check" guard against possible malformed output from the API server.

I believe it's the latter (and sufficient), based on the limited number of RRs which can fit in a 64KiB DNS message. This might be worth noting in a comment so this isn't confused for a tunable later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants