From: Egor Date: Sun, 22 Oct 2023 18:08:23 +0000 (+0300) Subject: trie_set: always check the error X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=385e21641e9f08da49a3584cf72cc3c246f3b05f;p=patchyircd.git trie_set: always check the error and guarantee that no errors can occur on unset --- diff --git a/src/irc.c b/src/irc.c index dd4f3c7..678b67e 100644 --- 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); diff --git a/src/main.c b/src/main.c index 60c0a10..2d03cf3 100644 --- a/src/main.c +++ b/src/main.c @@ -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; diff --git a/src/map_dynarr.h b/src/map_dynarr.h index eba2332..e166dba 100644 --- a/src/map_dynarr.h +++ b/src/map_dynarr.h @@ -1,6 +1,15 @@ #ifndef MAP_DYNARR_H_ #define MAP_DYNARR_H_ #include +#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 diff --git a/src/net.c b/src/net.c index 83d90db..e04e1ee 100644 --- 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); diff --git a/src/trie.c b/src/trie.c index 630a172..6443d38 100644 --- a/src/trie.c +++ b/src/trie.c @@ -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; diff --git a/src/trie.h b/src/trie.h index ef21dbd..71b36dd 100644 --- a/src/trie.h +++ b/src/trie.h @@ -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