diff --git a/ares/CHANGES b/ares/CHANGES index 000321719..d721dd595 100644 --- a/ares/CHANGES +++ b/ares/CHANGES @@ -1,5 +1,9 @@ Changelog for the c-ares project +* May 5 2008 (Yang Tse) + +- Improved parsing of resolver configuration files. + * April 4 2008 (Daniel Stenberg) - Eino Tuominen improved the code when a file is used to seed the randomizer. diff --git a/ares/RELEASE-NOTES b/ares/RELEASE-NOTES index aff018aa2..5387ae9ab 100644 --- a/ares/RELEASE-NOTES +++ b/ares/RELEASE-NOTES @@ -1,9 +1,9 @@ This is what's new and changed in the c-ares 1.5.2 release: - o + o improved parsing of resolver configuration files Thanks go to these friendly people for their efforts and contributions: - + Yang Tse Have fun! diff --git a/ares/ares_init.c b/ares/ares_init.c index 583f98f45..9b655a867 100644 --- a/ares/ares_init.c +++ b/ares/ares_init.c @@ -1245,16 +1245,61 @@ static int set_options(ares_channel channel, const char *str) static char *try_config(char *s, const char *opt) { size_t len; + ssize_t i; + ssize_t j; + char *p; - len = strlen(opt); - if (strncmp(s, opt, len) != 0 || !ISSPACE(s[len])) + if (!s || !opt) + /* no line or no option */ return NULL; - s += len; - while (ISSPACE(*s)) - s++; - return s; -} + /* trim line comment */ + for (i = 0; s[i] && s[i] != '#'; ++i); + s[i] = '\0'; + + /* trim trailing whitespace */ + for (j = i-1; j >= 0 && ISSPACE(s[j]); --j); + s[++j] = '\0'; + + /* skip leading whitespace */ + for (i = 0; s[i] && ISSPACE(s[i]); ++i); + p = &s[i]; + + if (!*p) + /* empty line */ + return NULL; + + if ((len = strlen(opt)) == 0) + /* empty option */ + return NULL; + + if (strncmp(p, opt, len) != 0) + /* line and option do not match */ + return NULL; + + /* skip over given option name */ + p += len; + + if (!*p) + /* no option value */ + return NULL; + + if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p)) + /* whitespace between option name and value is mandatory + for given option names which do not end with ':' or '=' */ + return NULL; + + /* skip over whitespace */ + while (*p && ISSPACE(*p)) + p++; + + if (!*p) + /* no option value */ + return NULL; + + /* return pointer to option value */ + return p; +} #endif static const char *try_option(const char *p, const char *q, const char *opt)