X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/c9433c53ad292c2f7ec05aa9d083767f95d07858..8f2cf8f5adaa08ef84b47bf9bc2f71e39236c22d:/src/src/parse.c diff --git a/src/src/parse.c b/src/src/parse.c index a290ae7c3..cf673e716 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -3,7 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ -/* Copyright (c) The Exim Maintainers 2020 */ +/* Copyright (c) The Exim Maintainers 2020 - 2021 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for parsing addresses */ @@ -1243,7 +1243,7 @@ Returns: FF_DELIVERED addresses extracted int parse_forward_list(const uschar *s, int options, address_item **anchor, - uschar **error, const uschar *incoming_domain, uschar *directory, + uschar **error, const uschar *incoming_domain, const uschar *directory, error_block **syntax_errors) { int count = 0; @@ -1252,18 +1252,15 @@ DEBUG(D_route) debug_printf("parse_forward_list: %s\n", s); for (;;) { - int len; - int special = 0; - int specopt = 0; - int specbit = 0; - const uschar *ss, *nexts; - address_item *addr; + int len, special = 0, specopt = 0, specbit = 0; + const uschar * ss, * nexts; + address_item * addr; BOOL inquote = FALSE; for (;;) { while (isspace(*s) || *s == ',') s++; - if (*s == '#') { while (*s != 0 && *s != '\n') s++; } else break; + if (*s == '#') { while (*s && *s != '\n') s++; } else break; } /* When we reach the end of the list, we return FF_DELIVERED if any child @@ -1287,8 +1284,8 @@ for (;;) #ifdef NEVER if (count > 0) return FF_DELIVERED; /* Something was generated */ - if (syntax_errors == NULL || /* Not skipping syntax errors, or */ - *syntax_errors == NULL) /* we didn't actually skip any */ + if (!syntax_errors || /* Not skipping syntax errors, or */ + !*syntax_errors) /* we didn't actually skip any */ return FF_NOTDELIVERED; *error = string_sprintf("no addresses generated: syntax error in %s: %s", @@ -1311,7 +1308,7 @@ for (;;) /* Remove any trailing spaces; we know there's at least one non-space. */ - while (isspace((ss[-1]))) ss--; + while (isspace(ss[-1])) ss--; /* We now have s->start and ss->end of the next address. Remove quotes if they completely enclose, remembering the address started with a quote @@ -1324,7 +1321,7 @@ for (;;) ss--; inquote = TRUE; while (s < ss && isspace(*s)) s++; - while (ss > s && isspace((ss[-1]))) ss--; + while (ss > s && isspace(ss[-1])) ss--; } /* Set up the length of the address. */ @@ -1354,15 +1351,16 @@ for (;;) if (special) { - uschar *ss = Ustrchr(s+1, ':') + 1; + uschar * ss = Ustrchr(s+1, ':') + 1; /* line after the special... */ if ((options & specopt) == specbit) { *error = string_sprintf("\"%.*s\" is not permitted", len, s); return FF_ERROR; } - while (*ss && isspace(*ss)) ss++; - while (s[len] && s[len] != '\n') len++; - *error = string_copyn(ss, s + len - ss); + while (*ss && isspace(*ss)) ss++; /* skip leading whitespace */ + if ((len = Ustrlen(ss)) > 0) /* ignore trailing newlines */ + for (const uschar * t = ss + len - 1; t >= ss && *t == '\n'; t--) len--; + *error = string_copyn(ss, len); /* becomes the error */ return special; } @@ -1373,14 +1371,14 @@ for (;;) if (Ustrncmp(s, ":include:", 9) == 0) { - uschar *filebuf; + uschar * filebuf; uschar filename[256]; const uschar * t = s+9; int flen = len - 9; int frc; struct stat statbuf; - address_item *last; - FILE *f; + address_item * last; + FILE * f; while (flen > 0 && isspace(*t)) { t++; flen--; } @@ -1390,7 +1388,7 @@ for (;;) return FF_ERROR; } - if (flen > 255) + if (flen > sizeof(filename)-1) { *error = string_sprintf("included file name \"%s\" is too long", t); return FF_ERROR; @@ -1416,16 +1414,22 @@ for (;;) return FF_ERROR; } - if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for included file not permitted\n", filename))) + if (is_tainted(filename)) + { + *error = string_sprintf("Tainted name '%s' for included file not permitted\n", + filename); return FF_ERROR; + } /* Check file name if required */ if (directory) { int len = Ustrlen(directory); - uschar *p = filename + len; + uschar * p; + while (len > 0 && directory[len-1] == '/') len--; /* ignore trailing '/' */ + p = filename + len; if (Ustrncmp(filename, directory, len) != 0 || *p != '/') { *error = string_sprintf("included file %s is not in directory %s", @@ -1440,7 +1444,7 @@ for (;;) with a flag that fails symlinks. */ { - int fd = exim_open2(CS directory, O_RDONLY); + int fd = exim_open2(CCS directory, O_RDONLY); if (fd < 0) { *error = string_sprintf("failed to open directory %s", directory); @@ -1450,9 +1454,10 @@ for (;;) { uschar temp; int fd2; - uschar * q = p; + uschar * q = p + 1; /* skip dividing '/' */ - while (*++p && *p != '/') ; + while (*q == '/') q++; /* skip extra '/' */ + while (*++p && *p != '/') ; /* end of component */ temp = *p; *p = '\0'; @@ -1613,16 +1618,16 @@ for (;;) is no domain, treat it as a file or pipe. If it was a quoted item, remove the quoting occurrences of \ within it. */ - if ((*s_ltd == '|' || *s_ltd == '/') && (recipient == NULL || domain == 0)) + if ((*s_ltd == '|' || *s_ltd == '/') && (!recipient || domain == 0)) { - uschar *t = store_get(Ustrlen(s_ltd) + 1, is_tainted(s_ltd)); - uschar *p = t; - uschar *q = s_ltd; - while (*q != 0) + uschar * t = store_get(Ustrlen(s_ltd) + 1, is_tainted(s_ltd)); + uschar * p = t, * q = s_ltd; + + while (*q) { if (inquote) { - *p++ = (*q == '\\')? *(++q) : *q; + *p++ = *q == '\\' ? *++q : *q; q++; } else *p++ = *q++; @@ -1653,13 +1658,15 @@ for (;;) if (syntax_errors) { - error_block *e = store_get(sizeof(error_block), FALSE); - error_block *last = *syntax_errors; - if (!last) *syntax_errors = e; else + error_block * e = store_get(sizeof(error_block), FALSE); + error_block * last = *syntax_errors; + if (last) { while (last->next) last = last->next; last->next = e; } + else + *syntax_errors = e; e->next = NULL; e->text1 = *error; e->text2 = s_ltd; @@ -1676,10 +1683,10 @@ for (;;) /* Address was successfully parsed. Rewrite, and then make an address block. */ - recipient = ((options & RDO_REWRITE) != 0)? - rewrite_address(recipient, TRUE, FALSE, global_rewrite_rules, - rewrite_existflags) : - rewrite_address_qualify(recipient, TRUE); /*XXX loses track of const */ + recipient = options & RDO_REWRITE + ? rewrite_address(recipient, TRUE, FALSE, global_rewrite_rules, + rewrite_existflags) + : rewrite_address_qualify(recipient, TRUE); /*XXX loses track of const */ addr = deliver_make_addr(US recipient, TRUE); /* TRUE => copy recipient, so deconst ok */ }