Skip to content

Commit

Permalink
Correct seg fault when using -s option.
Browse files Browse the repository at this point in the history
NULL lists are now invalid. Previously, NULL lists were 
interchangeable with an empty list, but that was a mistake.
  • Loading branch information
dleonard committed Oct 13, 2008
1 parent 259663b commit 36e6ca1
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 49 deletions.
34 changes: 21 additions & 13 deletions dnsupdate.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ main(int argc, char **argv)
size_t udatalen;
char reverse[4 * 4 + sizeof "IN-ADDR.ARPA"];
char **domain_list;
char **ns_list;

err_enable_syslog(1);

Expand Down Expand Up @@ -1254,17 +1255,21 @@ main(int argc, char **argv)
* Step 2: Figure out which nameserver to update against
*/

/* The user may have supplied a list of nameservers with -n */
server_list = user_servers;
auth_domain = user_auth_domain;

if (!server_list) {
/* The user may have supplied a list of nameservers with -n */
server_list = NULL;
if (user_servers)
server_list = list_dup(user_servers);

if (list_is_empty_or_null(server_list)) {
/* Perform an SOA query on the record name we want to update.
* The primary server from the SOA response becomes the
* first host we will try. */
if (query_soa(ns, name, auth_domainbuf, sizeof auth_domainbuf,
auth_primary, sizeof auth_primary) == 0)
{
list_free(server_list);
server_list = list_from_single(auth_primary);
/* Later we will use auth_domainbuf to find more servers */
extend_servers_on_fail = 1;
Expand All @@ -1277,24 +1282,26 @@ main(int argc, char **argv)
}

/* If we still don't have a list of servers, ask VAS for DCs */
if (vas_ctx && !server_list) {
if (vas_ctx && list_is_empty_or_null(server_list)) {
char **vas_servers = NULL;
error = vas_info_servers(vas_ctx, NULL, NULL, VAS_SRVINFO_TYPE_DC,
&vas_servers);
if (error) {
if (error)
warnx("vas_info_servers: %s", vas_err_get_string(vas_ctx, 1));
server_list = NULL;
} else {
else {
list_free(server_list);
server_list = list_dup(vas_servers);
vas_info_servers_free(vas_ctx, vas_servers);
}
}

/* Last resort: try all nameservers in resolv.conf */
if (!server_list)
if (list_is_empty_or_null(server_list)) {
list_free(server_list);
server_list = resconf_get("nameserver");
}

if (!server_list || !*server_list)
if (list_is_empty_or_null(server_list))
errx(1, "Cannot determine nameservers to update against");

if (!auth_domain)
Expand All @@ -1321,9 +1328,10 @@ main(int argc, char **argv)
*/

ret = -1;
ns_list = NULL;
for (serverp = server_list; ; serverp++) {
if (!*serverp && extend_servers_on_fail) {
char **ns_list = NULL, **lp;
char **lp;
/* If we exhausted the server list obtained from an SOA query
* then try adding more by performing an NS query on
* the authoritative domain itself */
Expand All @@ -1334,8 +1342,7 @@ main(int argc, char **argv)
warnx("unable to get NS records for %s", auth_domainbuf);
for (lp = server_list; *lp; lp++)
list_remove(ns_list, *lp);
list_free(server_list);
server_list = serverp = ns_list;
serverp = ns_list;
}
if (!serverp || !*serverp) {
if (verbose)
Expand Down Expand Up @@ -1402,8 +1409,9 @@ main(int argc, char **argv)
name,
utype == DNS_TYPE_A ? "A" : "PTR",
(ret == 0) ? "succeeded" : "failed");
list_free(server_list);
list_free(ns_list);
}
list_free(server_list);

dnstcp_close(&ns);

Expand Down
33 changes: 28 additions & 5 deletions list-t.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,35 @@ int main()
char foo[] = "foo";
char bar[] = "bar";

list = NULL;
/* Check that assert is working */
ret = 0;
assert(ret = 1);
if (!ret) { fprintf(stderr, "assert() not working\n"); exit(1); }

assert(list_is_empty_or_null(NULL));

list = list_new();
assert(list != NULL);
assert(list[0] == NULL);
assert(list_length(list) == 0);
assert(list_is_empty_or_null(list));
list2 = list_dup(list);
assert(list2 != NULL);
assert(list2[0] == NULL);
assert(list_length(list2) == 0);
assert(list_is_empty_or_null(list2));
list_free(list);
list_free(list2);

list = NULL;
list = list_new();
ret = list_append(&list, bar);
assert(ret == 1);
assert(list != NULL);
assert(streq(list[0], "bar"));
assert(list[0] != bar);
assert(list[1] == NULL);
assert(list_length(list) == 1);
assert(!list_is_empty_or_null(list));
ret = list_append(&list, foo);
assert(ret == 2);
assert(list != NULL);
Expand All @@ -39,6 +51,7 @@ int main()
assert(list[1] != foo);
assert(list[2] == NULL);
assert(list_length(list) == 2);
assert(!list_is_empty_or_null(list));
list_free(list);

list = list_from_single(foo);
Expand All @@ -64,13 +77,16 @@ int main()
list_free(list2);

list = list_from_string("");
assert(list == NULL);
assert(list != NULL);
assert(list_length(list) == 0);

list = list_from_string(" ");
assert(list == NULL);
assert(list != NULL);
assert(list_length(list) == 0);

list = list_from_string(" ");
assert(list == NULL);
assert(list != NULL);
assert(list_length(list) == 0);

list = list_from_string("word");
assert(list != NULL);
Expand Down Expand Up @@ -202,6 +218,13 @@ int main()
assert(list[4] == NULL);
assert(list_length(list) == 4);

list_remove(list, "f");
list_remove(list, "b");
list_remove(list, "d");
list_remove(list, "c");
assert(list != NULL);
assert(list_length(list) == 0);

list_free(list);

exit(0);
Expand Down
85 changes: 55 additions & 30 deletions list.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
#include "common.h"
#include "list.h"

static char **
list_alloc(int len)
{
char **list;

if (!(list = (char **)malloc((len + 1) * sizeof (char *))))
return NULL;
list[len] = NULL;
return list;
}

/* Creates a list out of a whitespace separated string.
* Returns NULL on error */
char **
Expand All @@ -17,8 +28,9 @@ list_from_string(const char *string)
while (*string == ' ')
string++;

/* Copy words into the list */
list = NULL;
if (!(list = list_alloc(0)))
return NULL;

s = string;
for (;;) {
while (*s == ' ')
Expand All @@ -29,7 +41,8 @@ list_from_string(const char *string)
while (*s && *s != ' ')
s++;
wordlen = s - start;
word = malloc(wordlen + 1);
/* Duplicate s[start..start+wordlen] */
word = (char *)malloc(wordlen + 1);
if (!word) {
list_free(list);
return NULL;
Expand All @@ -42,39 +55,49 @@ list_from_string(const char *string)
return list;
}

/* Returns the length of a list */
/* Returns the length of a list. Lists must not be NULL. */
int
list_length(char **list)
{
int len;

if (!list)
return 0;
for (len = 0; *list; list++)
len++;
return len;
}

/* Returns true if the list is empty or null */
int
list_is_empty_or_null(char **list)
{
return !list || !*list;
}

char **
list_new()
{
return list_alloc(0);
}

/* Create a list from a single item */
char **
list_from_single(const char *item)
{
char **list;
char *item_copy;

item_copy = strdup(item);
list = (char **)malloc(sizeof (char *) * 2);
if (!item_copy || !list) {
if (item_copy) free(item_copy);
if (list) free(list);
if (!(item_copy = strdup(item)))
return NULL;
if (!(list = list_alloc(1))) {
free(item_copy);
return NULL;
}
list[0] = item_copy;
list[1] = NULL;
return list;
}

/* Append an item to the list.
/* Append an item to the list. The item is copied with strdup.
* List must already have been allocated.
* Returns new length on list success, or -1 on error */
int
list_append(char ***listp, const char *item)
Expand All @@ -87,36 +110,35 @@ list_append(char ***listp, const char *item)
nwords = list_length(*listp);

/* Allocate new storage */
new_list = (char **)malloc(sizeof (char *) * (nwords + 1 + 1));
item_copy = strdup(item);
if (!new_list || !item_copy) {
if (new_list) free(new_list);
if (item_copy) free(item_copy);
if (!(new_list = list_alloc(nwords + 1)))
return -1;

if (!(item_copy = strdup(item))) {
free(new_list);
return -1;
}

if (*listp)
memcpy(new_list, *listp, sizeof (char *) * nwords);
new_list[nwords] = item_copy;
new_list[nwords + 1] = NULL;

if (*listp)
free(*listp);
*listp = new_list;
return nwords + 1;
}

/* Frees a previously allocated list */
/* Frees a previously allocated list. OK if list is NULL */
void
list_free(char **list)
{
char **l;

if (!list)
return;
for (l = list; *l; l++)
free(*l);
free(list);
if (list) {
for (l = list; *l; l++)
free(*l);
free(list);
}
}

/* Returns a duplicate of a list */
Expand All @@ -127,10 +149,15 @@ list_dup(char **list)
int i, nwords;

nwords = list_length(list);
list_copy = (char **)malloc(sizeof (char *) * (nwords + 1));
if (!(list_copy = list_alloc(nwords)))
return NULL;
for (i = 0; i < nwords; i++)
list_copy[i] = strdup(list[i]);
list_copy[nwords] = NULL;
if (!(list_copy[i] = strdup(list[i]))) {
while (i--)
free(list_copy[i]);
free(list_copy);
return NULL;
}
return list_copy;
}

Expand All @@ -141,8 +168,6 @@ list_remove(char **list, const char *item)
{
char **ok;

if (!list)
return;
for (ok = list; *list; list++)
if (strcmp(*list, item) == 0)
free(*list);
Expand Down
4 changes: 3 additions & 1 deletion list.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
/* A list is a null terminated array of allocated strings */
char **list_from_string(const char *s);
char **list_from_single(const char *item);
void list_free(char **list);
void list_free(char **list); /* NULL list ok */
int list_append(char ***listp, const char *item);
char **list_dup(char **list);
char **list_new(void);
int list_length(char **list);
void list_remove(char **list, const char *item);
int list_is_empty_or_null(char **list); /* NULL list ok */

0 comments on commit 36e6ca1

Please sign in to comment.