]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Remove infinite loop on ISC_R_NOFILE
authorMark Andrews <marka@isc.org>
Thu, 18 Jan 2024 07:54:09 +0000 (18:54 +1100)
committerMark Andrews <marka@isc.org>
Tue, 7 May 2024 00:01:12 +0000 (10:01 +1000)
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

index 9f7258b3b32c959348fe41c25cf9b854e21acc3c..db42558a7488a57317f9a6e4d02304621fdaf6b7 100644 (file)
@@ -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) { \