]> PatchyGit - patchyircd.git/commitdiff
trie_set: always check the error
authorEgor <egor@patchysicp.xyz>
Sun, 22 Oct 2023 18:08:23 +0000 (21:08 +0300)
committerEgor <egor@patchysicp.xyz>
Sun, 22 Oct 2023 18:08:23 +0000 (21:08 +0300)
and guarantee that no errors can occur on unset

src/irc.c
src/main.c
src/map_dynarr.h
src/net.c
src/trie.c
src/trie.h

index dd4f3c7..678b67e 100644 (file)
--- a/src/irc.c
+++ b/src/irc.c
@@ -406,7 +406,8 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        return err_nosuchchannel(client, args[0]), sendbuf(client), 0;
                if (!trie_get(&chan->members, client->key))
                        return err_notonchannel(client, chan), sendbuf(client), 0;
-               trie_set(&chan->o, client->key, client, NULL);
+               if (trie_set(&chan->o, client->key, client, NULL) == -1)
+                       abort();
                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick);
                sendbuf_chan(chan);
        } else if(strcmp(command, "JOIN") == 0) {
@@ -512,8 +513,10 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        return err_nosuchnick(client, args[0]), sendbuf(client), 0;
                if (trie_get(&chan->members, cl->key))
                        return err_useronchannel(client, cl->nick, chan), sendbuf(client), 0;
-               trie_set(&chan->invitees, cl->nick, cl, NULL);
-               trie_set(&cl->invites, chan->name, chan, NULL);
+               if (trie_set(&chan->invitees, cl->nick, cl, NULL) == -1)
+                       abort();
+               if (trie_set(&cl->invites, chan->name, chan, NULL) == -1)
+                       abort();
                rpl_inviting(client, cl, chan);
                sendbuf(client);
                msg_invite(client, cl, chan);
@@ -918,7 +921,8 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                                                if (strchr(mask, ' '))
                                                        break; // TODO: error msg
                                                stringlower(mask);
-                                               trie_set(list, mask, is_plus ? mask /* dummy */ : NULL, NULL);
+                                               if (trie_set(list, mask, is_plus ? mask /* dummy */ : NULL, NULL) == -1)
+                                                       abort();
                                                char which[2] = {*p, 0};
                                                copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
                                                                client->nick, client->username, client->hostname,
@@ -942,7 +946,8 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                                                        err_usernotinchannel(client, cl->nick, chan), sendbuf(client);
                                                        break;
                                                }
-                                               trie_set(*p == 'o' ? &chan->o : &chan->v, cl->key, is_plus ? cl : NULL, NULL);
+                                               if (trie_set(*p == 'o' ? &chan->o : &chan->v, cl->key, is_plus ? cl : NULL, NULL) == -1)
+                                                       abort();
                                                copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
                                                                client->nick, client->username, client->hostname,
                                                                chan->name, is_plus?"+":"-", which, cl->nick);
@@ -1213,20 +1218,23 @@ void setNick(struct client_data *client, char* nickname) {
                msg_nick(client, nickname);
                sendbuf(client);
                sendbuf_visible(client);
-               trie_set(&client_map, client->key, NULL, NULL);
+               trie_unset(&client_map, client->key, NULL);
                struct trie_find *f = NULL;
                if (trie_findfirst(&f, &client->channels) == 1)
                        do {
                                struct channel *chan = f->n->value;
-                               trie_set(&chan->members, client->key, NULL, NULL);
-                               trie_set(&chan->members, key, client, NULL);
+                               trie_unset(&chan->members, client->key, NULL);
+                               if (trie_set(&chan->members, key, client, NULL) == -1)
+                                       abort();
                                void *old;
-                               trie_set(&chan->o, client->key, NULL, &old);
+                               trie_unset(&chan->o, client->key, &old);
                                if (old)
-                                       trie_set(&chan->o, key, client, NULL);
-                               trie_set(&chan->v, client->key, NULL, &old);
+                                       if (trie_set(&chan->o, key, client, NULL) == -1)
+                                               abort();
+                               trie_unset(&chan->v, client->key, &old);
                                if (old)
-                                       trie_set(&chan->v, key, client, NULL);
+                                       if (trie_set(&chan->v, key, client, NULL) == -1)
+                                               abort();
                        } while(trie_findnext(&f) == 1);
                free(client->nick);
                free(client->key);
@@ -1365,22 +1373,22 @@ void channel_part(struct client_data *client, struct channel *chan, const char *
                msg_part(client, chan, *reason ? reason : NULL);
                sendbuf_chan(chan);
        }
-       trie_set(&client->channels, chan->key, NULL, NULL);
-       trie_set(&chan->members, client->key, NULL, NULL);
-       trie_set(&chan->o, client->key, NULL, NULL);
-       trie_set(&chan->v, client->key, NULL, NULL);
+       trie_unset(&client->channels, chan->key, NULL);
+       trie_unset(&chan->members, client->key, NULL);
+       trie_unset(&chan->o, client->key, NULL);
+       trie_unset(&chan->v, client->key, NULL);
        chan->member_count--;
        if (!chan->member_count && !(chan->dmode & DMODE_PERSIST))
                channel_kill(chan);
 }
 void channel_kill(struct channel *chan)
 {
-       trie_set(&channel_map, chan->key, NULL, NULL);
+       trie_unset(&channel_map, chan->key, NULL);
        struct trie_find *f = NULL;
        if (trie_findfirst(&f, &chan->invitees) == 1)
                do {
                        struct client_data *cl = f->n->value;
-                       trie_set(&cl->invites, chan->key, NULL, NULL);
+                       trie_unset(&cl->invites, chan->key, NULL);
                } while(trie_findnext(&f) == 1);
        free(chan->key);
        free(chan->name);
index 60c0a10..2d03cf3 100644 (file)
@@ -242,7 +242,8 @@ int main(int argc, char *argv[])
                } else if(!strcmp(argv[i], "--autojoin")) {
                        if (i + 1 >= argc)
                                return fprintf(stderr, "not enough parameters\n"), 1;
-                       trie_set(&autojoin, argv[i+1], (void*)1, NULL);
+                       if (trie_set(&autojoin, argv[i+1], (void*)1, NULL) == -1)
+                               abort();
                        i += 1;
                } else {
                        return fprintf(stderr, "unknown flag '%s'\n", argv[i]), 1;
index eba2332..e166dba 100644 (file)
@@ -1,6 +1,15 @@
 #ifndef MAP_DYNARR_H_
 #define MAP_DYNARR_H_
 #include <stddef.h>
+#if defined(__has_c_attribute)
+#    if __has_c_attribute(nodiscard)
+#        define NODISCARD [[nodiscard]]
+#    else
+#        define NODISCARD
+#    endif
+#else
+#    define NODISCARD
+#endif
 struct map_dynarr_value {
        char *key;
        void *value;
@@ -11,7 +20,8 @@ struct map_dynarr {
 };
 typedef struct map_dynarr map_t;
 void *trie_get(map_t *root, const char *key);
-int trie_set(map_t *root, const char *key, const void *value, void **oldvalue);
+NODISCARD int trie_set(map_t *root, const char *key, const void *value, void **oldvalue);
+#define trie_unset(root, key, oldvalue) ((void)trie_set((root), (key), 0, (oldvalue)))
 void trie_free(map_t *root);
 struct trie_find {
        char *key;
@@ -19,6 +29,6 @@ struct trie_find {
        map_t *_root;
        int _cap;
 };
-int trie_findfirst(struct trie_find **pf, map_t *root);
-int trie_findnext(struct trie_find **pf);
+NODISCARD int trie_findfirst(struct trie_find **pf, map_t *root);
+NODISCARD int trie_findnext(struct trie_find **pf);
 #endif
index 83d90db..e04e1ee 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -72,12 +72,12 @@ void killConnection(struct client_data *cl, int byChoice)
        free(f);
        /* Remove from client_map and get rid of the pending invites */
        if (cl->key) {
-               trie_set(&client_map, cl->key, NULL, NULL);
+               trie_unset(&client_map, cl->key, NULL);
                struct trie_find *f = NULL;
                if (trie_findfirst(&f, &cl->invites) == 1)
                        do {
                                struct channel *chan = f->n->value;
-                               trie_set(&chan->invitees, cl->key, NULL, NULL);
+                               trie_unset(&chan->invitees, cl->key, NULL);
                        } while(trie_findnext(&f) == 1);
        }
        trie_free(&cl->channels);
index 630a172..6443d38 100644 (file)
@@ -48,6 +48,8 @@ int trie_set(map_t *root, const char *key, const void *value, void **oldvalue)
                *oldvalue = NULL;
        struct trie_node *n = *root;
        if (!n) { // create root node
+               if (!value)
+                       return 0;
                n = malloc(trie_node_size(1));
                if (!n)
                        return -1;
index ef21dbd..71b36dd 100644 (file)
@@ -4,6 +4,15 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+#if defined(__has_c_attribute)
+#    if __has_c_attribute(nodiscard)
+#        define NODISCARD [[nodiscard]]
+#    else
+#        define NODISCARD
+#    endif
+#else
+#    define NODISCARD
+#endif
 // all complexity is in terms of n = strlen(key) and s = size of the character set
 struct trie_node {
        unsigned char key;
@@ -17,7 +26,8 @@ typedef struct trie_node *map_t;
 // get value from trie O(n log s)
 void *trie_get(map_t *root, const char *key);
 // set value in trie O(ns)
-int trie_set(map_t *root, const char *key, const void *value, void **oldvalue);
+NODISCARD int trie_set(map_t *root, const char *key, const void *value, void **oldvalue);
+#define trie_unset(root, key, oldvalue) ((void)trie_set((root), (key), 0, (oldvalue)))
 // free a trie
 void trie_free(map_t *root);
 struct trie_find {
@@ -26,8 +36,8 @@ struct trie_find {
        size_t cap;
        char key[1];
 };
-int trie_findfirst(struct trie_find **pf, map_t *root);
-int trie_findnext(struct trie_find **pf);
+NODISCARD int trie_findfirst(struct trie_find **pf, map_t *root);
+NODISCARD int trie_findnext(struct trie_find **pf);
 #ifdef __cplusplus
 }
 #endif