From 21b015da2c3d4baa447443f28ad41bab3829bda5 Mon Sep 17 00:00:00 2001 From: lda Date: Tue, 4 Jun 2024 13:45:12 +0200 Subject: [PATCH] [MOD/WIP] Fix double-free on PL checks --- src/Room.c | 72 ++++++++++++++++++++++++++++------------------ src/include/Room.h | 6 ++++ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/Room.c b/src/Room.c index 7670dbf..604f504 100644 --- a/src/Room.c +++ b/src/Room.c @@ -23,12 +23,12 @@ * SOFTWARE. */ +#include #include #include -/*#include "Cytoplasm/Stream.h"*/ -#include "Cytoplasm/HashMap.h" -#include "Parser.h" -#include "User.h" +#include +#include +#include #include #include @@ -87,6 +87,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) HashMap *content, *event, *override, *pl_content; Array *initial_states; JsonValue *val; + int64_t pl = 100; size_t i; char *join_rules_preset = NULL; @@ -137,7 +138,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) content = HashMapCreate(); JsonSet( content, - JsonValueInteger(100), + JsonValueInteger(pl), 2, "users", sender_str); override = req->power_level_content_override; while (override && HashMapIterate(override, &key, (void **) &val)) @@ -150,7 +151,6 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) } HashMapSet(content, key, JsonValueDuplicate(val)); } - pl_content = JsonDuplicate(content); event = RoomEventCreate(sender_str, "m.room.power_levels", "", content); JsonFree(RoomEventSend(room, event)); JsonFree(event); @@ -273,6 +273,8 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) Free(serverStr); } /* Invites */ + pl_content = HashMapCreate(); + JsonSet(pl_content, JsonValueInteger(pl), 2, "users", sender_str); for (i = 0; i < ArraySize(req->invite); i++) { char *user_id = ArrayGet(req->invite, i); @@ -283,33 +285,23 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) break; } - content = HashMapCreate(); - if (req->is_direct) - { - JsonSet(content, JsonValueBoolean(true), 1, "is_direct"); - } - JsonSet(content, JsonValueString("invite"), 1, "membership"); - event = RoomEventCreate(sender_str, "m.room.member", user_id, content); - JsonFree(RoomEventSend(room, event)); - JsonFree(event); + RoomSendInvite(user, req->is_direct, user_id, room); if (trusted_room) { - JsonValue *own = JsonGet(pl_content, 2, "users", sender_str); - JsonValueFree(JsonSet( - pl_content, JsonValueDuplicate(own), - 2, "users", user_id)); + JsonValue *own = JsonValueInteger(pl); + JsonSet(pl_content, own, 2, "users", user_id); } } - JsonValueFree(JsonSet( - DbJson(room->leaves_ref), - JsonValueBoolean(req->is_direct), 1, "is_direct")); event = RoomEventCreate(sender_str, "m.room.power_levels", "", pl_content); JsonFree(RoomEventSend(room, event)); JsonFree(event); + JsonValueFree(JsonSet( + DbJson(room->leaves_ref), + JsonValueBoolean(req->is_direct), 1, "is_direct")); /* TODO: The rest of the events mandated by the specification on * POST /createRoom, and error management. */ @@ -1293,8 +1285,8 @@ AuthorisePowerLevelsV1(Room * room, PduV1 pdu, HashMap *state) \ new = JsonGet(pdu.content, 2, prop, ev_type); \ old_pl = ParsePL(new, INT64_MAX); \ - if (((new_pl = ParsePL(new, INT64_MAX)) == INT64_MAX || \ - new_pl != old_pl) && old_pl > userpl) \ + if (((new_pl = ParsePL(new, INT64_MAX)) != INT64_MAX) && \ + ((new_pl != old_pl) && old_pl > userpl)) \ { \ flag = false; \ } \ @@ -1302,7 +1294,6 @@ AuthorisePowerLevelsV1(Room * room, PduV1 pdu, HashMap *state) if (!flag) \ { \ JsonFree(prev_plevent); \ - StateFree(state); \ return false; \ } \ flag = true @@ -1322,7 +1313,7 @@ AuthorisePowerLevelsV1(Room * room, PduV1 pdu, HashMap *state) \ old = JsonGet(prev_plevent, 3, "content", prop, ev_type); \ new_pl = ParsePL(ev_obj, INT64_MAX); \ - if (((old_pl = ParsePL(old, INT64_MAX)) == INT64_MAX || \ + if (((old_pl = ParsePL(old, INT64_MAX)) != INT64_MAX && \ new_pl != old_pl) && new_pl > userpl) \ { \ flag = false; \ @@ -1331,7 +1322,6 @@ AuthorisePowerLevelsV1(Room * room, PduV1 pdu, HashMap *state) if (!flag) \ { \ JsonFree(prev_plevent); \ - StateFree(state); \ return false; \ } \ flag = true @@ -1645,7 +1635,7 @@ RoomEventSendV1(Room * room, HashMap * event) finish: if (state) { - JsonFree(state); + StateFree(state); } if (pdu_object) { @@ -2005,3 +1995,29 @@ RoomFreeReverse(Array *arr) } ArrayFree(arr); } +void +RoomSendInvite(User *sender, bool direct, char *user, Room *room) +{ + HashMap *content, *event; + CommonID *senderID; + char *senderStr; + Config conf; + if (!sender || !user || !room) + { + return; + } + ConfigLock(room->db, &conf); + senderID = UserIdParse(UserGetName(sender), conf.serverName); + senderStr = ParserRecomposeCommonID(*senderID); + UserIdFree(senderID); + + content = HashMapCreate(); + JsonSet(content, JsonValueBoolean(direct), 1, "is_direct"); + JsonSet(content, JsonValueString("invite"), 1, "membership"); + event = RoomEventCreate(senderStr, "m.room.member", user, content); + JsonFree(RoomEventSend(room, event)); + JsonFree(event); + + ConfigUnlock(&conf); + Free(senderStr); +} diff --git a/src/include/Room.h b/src/include/Room.h index b5c54f0..0544020 100644 --- a/src/include/Room.h +++ b/src/include/Room.h @@ -138,6 +138,12 @@ extern int RoomPrevEventsSet(Room *, Array *); */ extern HashMap * RoomEventSend(Room *, HashMap *); +/** + * Sends an invite to a user in a room, and tries + * to notify such user of it. + */ +extern void RoomSendInvite(User *, bool, char *, Room *); + /** * Fetch a single event's PDU in a room into an * hashmap, given an event ID, from the database