From efd27bb82d89ad0ff0e52b93b30d0ef2cc5e2d8e Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 18 Jan 2024 18:54:09 +1100 Subject: [PATCH] Remove infinite loop on ISC_R_NOFILE When parsing a zonefile named-checkzone (and others) could loop infinitely if a directory was $INCLUDED. Record the error and treat as EOF when looking for multiple errors. This was found by Eric Sesterhenn from X41. --- lib/dns/master.c | 75 ++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/lib/dns/master.c b/lib/dns/master.c index 9f7258b3b3..db42558a74 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -204,33 +204,52 @@ grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *, static void loadctx_destroy(dns_loadctx_t *lctx); -#define GETTOKENERR(lexer, options, token, eol, err) \ - do { \ - result = gettoken(lexer, options, token, eol, callbacks); \ - switch (result) { \ - case ISC_R_SUCCESS: \ - break; \ - case ISC_R_UNEXPECTED: \ - goto insist_and_cleanup; \ - default: \ - if (MANYERRS(lctx, result)) { \ - SETRESULT(lctx, result); \ - LOGIT(result); \ - read_till_eol = true; \ - err goto next_line; \ - } else \ - goto log_and_cleanup; \ - } \ - if ((token)->type == isc_tokentype_special) { \ - result = DNS_R_SYNTAX; \ - if (MANYERRS(lctx, result)) { \ - SETRESULT(lctx, result); \ - LOGIT(result); \ - read_till_eol = true; \ - goto next_line; \ - } else \ - goto log_and_cleanup; \ - } \ +#define LCTX_MANYERRORS(lctx) (((lctx)->options & DNS_MASTER_MANYERRORS) != 0) + +#define GETTOKENERR(lexer, options, token, eol, err) \ + do { \ + result = gettoken(lexer, options, token, eol, callbacks); \ + switch (result) { \ + case ISC_R_SUCCESS: \ + break; \ + case ISC_R_NOTFILE: \ + /* Treat "bad" $INCLUDE as eof. */ \ + if (ictx->parent != NULL && LCTX_MANYERRORS(lctx)) { \ + SETRESULT(lctx, result); \ + COMMITALL; \ + lctx->inc = ictx->parent; \ + ictx->parent = NULL; \ + incctx_destroy(lctx->mctx, ictx); \ + RUNTIME_CHECK(isc_lex_close(lctx->lex) == \ + ISC_R_SUCCESS); \ + line = isc_lex_getsourceline(lctx->lex); \ + POST(line); \ + source = isc_lex_getsourcename(lctx->lex); \ + ictx = lctx->inc; \ + continue; \ + } \ + goto insist_and_cleanup; \ + case ISC_R_UNEXPECTED: \ + goto insist_and_cleanup; \ + default: \ + if (MANYERRS(lctx, result)) { \ + SETRESULT(lctx, result); \ + LOGIT(result); \ + read_till_eol = true; \ + err goto next_line; \ + } else \ + goto log_and_cleanup; \ + } \ + if ((token)->type == isc_tokentype_special) { \ + result = DNS_R_SYNTAX; \ + if (MANYERRS(lctx, result)) { \ + SETRESULT(lctx, result); \ + LOGIT(result); \ + read_till_eol = true; \ + goto next_line; \ + } else \ + goto log_and_cleanup; \ + } \ } while (0) #define GETTOKEN(lexer, options, token, eol) \ GETTOKENERR(lexer, options, token, eol, {}) @@ -283,7 +302,7 @@ loadctx_destroy(dns_loadctx_t *lctx); #define MANYERRS(lctx, result) \ ((result != ISC_R_SUCCESS) && (result != ISC_R_IOERROR) && \ - ((lctx)->options & DNS_MASTER_MANYERRORS) != 0) + LCTX_MANYERRORS(lctx)) #define SETRESULT(lctx, r) \ if ((lctx)->result == ISC_R_SUCCESS) { \