jcs
/subtext
/amendments
/336
board: Handle malloc/bile failures
jcs made amendment 336 about 1 year ago
--- board.c Wed Mar 1 09:51:32 2023
+++ board.c Wed Mar 1 22:00:33 2023
@@ -310,7 +310,7 @@ board_list_posts(struct session *s, struct board *boar
struct board_thread thread = { 0 };
struct board_post post;
struct board_fidonet_post fpost;
- short indent, j, k;
+ short indent, j, k, ret;
char *data;
session_printf(s, "{{B}}%s: %s (Page %ld of %ld){{/B}}\r\n",
@@ -329,11 +329,13 @@ board_list_posts(struct session *s, struct board *boar
if (board->fidonet_area[0]) {
size = bile_read_alloc(board->bile, BOARD_FIDONET_POST_RTYPE,
post_ids[n], &data);
- bile_unmarshall_object(board->bile,
+ ret = bile_unmarshall_object(board->bile,
board_fidonet_post_object_fields,
nboard_fidonet_post_object_fields, data, size, &fpost,
- sizeof(fpost), false, "board_list_posts");
+ sizeof(fpost), false);
xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ break;
strftime(time, sizeof(time), "%b %d", localtime(&fpost.time));
@@ -348,11 +350,13 @@ board_list_posts(struct session *s, struct board *boar
} else {
size = bile_read_alloc(board->bile, BOARD_POST_RTYPE,
post_ids[n], &data);
- bile_unmarshall_object(board->bile, board_post_object_fields,
- nboard_post_object_fields, data, size, &post, sizeof(post),
- false, "board_list_posts");
+ ret = bile_unmarshall_object(board->bile,
+ board_post_object_fields, nboard_post_object_fields, data,
+ size, &post, sizeof(post), false);
xfree(&data);
-
+ if (ret == BILE_ERR_NO_MEMORY)
+ break;
+
if (post.thread_id != thread.thread_id) {
if (thread.thread_id) {
if (thread.subject != NULL)
@@ -364,12 +368,13 @@ board_list_posts(struct session *s, struct board *boar
}
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
post.thread_id, &data);
- bile_unmarshall_object(board->bile,
+ ret = bile_unmarshall_object(board->bile,
board_thread_object_fields, nboard_thread_object_fields,
- data, size, &thread, sizeof(thread), true,
- "board_list_posts");
+ data, size, &thread, sizeof(thread), true);
xfree(&data);
-
+ if (ret == BILE_ERR_NO_MEMORY)
+ break;
+
for (j = 0; j < nitems(indent_parent_ids); j++)
indent_parent_ids[j] = 0;
}
@@ -449,15 +454,20 @@ board_compose(struct session *s, struct board *board,
return 0;
}
- if (initial_body)
- post.body = xstrdup(initial_body, "board_compose body");
+ if (initial_body) {
+ post.body = xstrdup(initial_body);
+ if (post.body == NULL)
+ return 0;
+ }
+
if (thread) {
post.thread_id = thread->thread_id;
post.parent_post_id = parent_post->id;
- } else
- thread = xmalloczero(sizeof(struct board_thread),
- "board_compose thread");
-
+ } else {
+ thread = xmalloczero(sizeof(struct board_thread));
+ if (thread == NULL)
+ return 0;
+ }
post.sender_user_id = s->user->id;
strlcpy(post.via, s->via, sizeof(post.via));
@@ -473,9 +483,11 @@ post_compose_start:
thread->subject);
session_flush(s);
} else {
- if (initial_subject && !thread->subject)
- thread->subject = xstrdup(initial_subject,
- "board_compose subject");
+ if (initial_subject && !thread->subject) {
+ thread->subject = xstrdup(initial_subject);
+ if (thread->subject == NULL)
+ return 0;
+ }
for (;;) {
session_printf(s, "{{B}}Subject:{{/B}} ");
@@ -619,7 +631,9 @@ board_post_read(struct session *s, struct board *board
short cc;
bool done = false, show_help = false;
- dopts = xmalloc(sizeof(opts), "board_post_read opts");
+ dopts = xmalloc(sizeof(opts));
+ if (dopts == NULL)
+ return 0;
memcpy(dopts, opts, sizeof(opts));
if (board->fidonet_area[0]) {
@@ -629,16 +643,17 @@ board_post_read(struct session *s, struct board *board
panic("failed fetching message %ld: %d", id,
bile_error(board->bile));
- bile_unmarshall_object(board->bile,
+ ret = bile_unmarshall_object(board->bile,
board_fidonet_post_object_fields,
nboard_fidonet_post_object_fields, data, size, &fpost,
- sizeof(fpost), true, "board_post_read post");
+ sizeof(fpost), true);
xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done_reading;
- if (!(s->user && s->user->is_sysop)) {
+ if (!(s->user && s->user->is_sysop))
/* disable deleting */
dopts[1].key[0] = '\0';
- }
strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S",
localtime(&fpost.time));
@@ -660,26 +675,28 @@ board_post_read(struct session *s, struct board *board
if (size == 0)
panic("failed fetching message %ld: %d", id,
bile_error(board->bile));
- bile_unmarshall_object(board->bile, board_post_object_fields,
- nboard_post_object_fields, data, size, &post, sizeof(post), true,
- "board_post_read post");
+ ret = bile_unmarshall_object(board->bile, board_post_object_fields,
+ nboard_post_object_fields, data, size, &post, sizeof(post), true);
xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done_reading;
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
post.thread_id, &data);
if (size == 0)
panic("failed fetching thread %ld: %d", post.thread_id,
bile_error(board->bile));
- bile_unmarshall_object(board->bile, board_thread_object_fields,
+ ret = bile_unmarshall_object(board->bile, board_thread_object_fields,
nboard_thread_object_fields, data, size, &thread,
- sizeof(thread), true, "board_post_read thread");
+ sizeof(thread), true);
xfree(&data);
-
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto done_reading;
+
if (!(s->user && (s->user->is_sysop ||
- s->user->id == post.sender_user_id))) {
+ s->user->id == post.sender_user_id)))
/* disable deleting */
dopts[1].key[0] = '\0';
- }
sender = user_username(post.sender_user_id);
@@ -733,7 +750,6 @@ board_post_read(struct session *s, struct board *board
post.id);
} else {
board_delete_post(s, board, &post, &thread);
-
session_logf(s, "Deleted post %ld (thread %ld)",
post.id, thread.thread_id);
}
@@ -769,7 +785,8 @@ board_post_read(struct session *s, struct board *board
break;
}
}
-
+
+done_reading:
xfree(&dopts);
if (board->fidonet_area[0]) {
@@ -813,9 +830,10 @@ board_find_post_ids(struct session *s, struct board *b
} else
nall_post_ids = size / sizeof(long);
- *post_ids = xcalloc(sizeof(long), MIN(limit, nall_post_ids),
- "post_ids");
-
+ *post_ids = xcalloc(sizeof(long), MIN(limit, nall_post_ids));
+ if (*post_ids == NULL)
+ return 0;
+
for (n = 0; n < nall_post_ids; n++) {
if (n < offset)
continue;
@@ -839,9 +857,9 @@ board_post_create(struct board *board, struct board_th
{
short ret;
char *data;
- size_t size;
+ size_t size, insert;
ssize_t n, j;
- size_t insert;
+ unsigned long *post_ids, *parent_post_ids;
if (post->parent_post_id == 0) {
thread->thread_id = bile_next_id(board->bile, BOARD_THREAD_RTYPE);
@@ -853,8 +871,7 @@ board_post_create(struct board *board, struct board_th
post->time = Time;
ret = bile_marshall_object(board->bile, board_post_object_fields,
- nboard_post_object_fields, post, &data, &size,
- "board_post_create post");
+ nboard_post_object_fields, post, &data, &size);
if (ret != 0 || size == 0) {
warn("failed to marshall new post object");
post->id = 0;
@@ -872,11 +889,17 @@ board_post_create(struct board *board, struct board_th
if (post->time > thread->last_post_at)
thread->last_post_at = post->time;
thread->nposts++;
- thread->post_ids = xreallocarray(thread->post_ids, thread->nposts,
+ post_ids = xreallocarray(thread->post_ids, thread->nposts,
sizeof(long));
- thread->parent_post_ids = xreallocarray(thread->parent_post_ids,
+ if (post_ids == NULL)
+ return 0;
+ thread->post_ids == post_ids;
+ parent_post_ids = xreallocarray(thread->parent_post_ids,
thread->nposts, sizeof(long));
-
+ if (parent_post_ids == NULL)
+ return 0;
+ thread->parent_post_ids = parent_post_ids;
+
/*
* Add new post id to thread post_ids, but put it in the right
* place so that reading post_ids will present the tree in order.
@@ -901,8 +924,7 @@ board_post_create(struct board *board, struct board_th
thread->parent_post_ids[insert] = post->parent_post_id;
ret = bile_marshall_object(board->bile, board_thread_object_fields,
- nboard_thread_object_fields, thread, &data, &size,
- "board_post_create thread");
+ nboard_thread_object_fields, thread, &data, &size);
if (ret != 0 || size == 0) {
warn("failed to marshall thread object");
post->id = 0;
@@ -928,7 +950,7 @@ board_delete_post(struct session *s, struct board *boa
struct board_post *post, struct board_thread *thread)
{
size_t size, n, nn;
- char *data;
+ char *data, *body;
char del[50];
short ret;
bool childs = false;
@@ -952,10 +974,13 @@ board_delete_post(struct session *s, struct board *boa
if (!childs) {
/* just zap this off the end of the tree */
- new_post_ids = xcalloc(thread->nposts - 1, sizeof(unsigned long),
- "board_delete_post new_post_ids");
+ new_post_ids = xcalloc(thread->nposts - 1, sizeof(unsigned long));
+ if (new_post_ids == NULL)
+ return;
new_parent_post_ids = xcalloc(thread->nposts - 1,
- sizeof(unsigned long), "board_delete_post new_parent_post_ids");
+ sizeof(unsigned long));
+ if (new_parent_post_ids == NULL)
+ return;
for (n = 0, nn = 0; n < thread->nposts; n++) {
if (thread->post_ids[n] == post->id)
@@ -981,8 +1006,7 @@ board_delete_post(struct session *s, struct board *boa
thread->parent_post_ids = new_parent_post_ids;
ret = bile_marshall_object(board->bile, board_thread_object_fields,
- nboard_thread_object_fields, thread, &data, &size,
- "board_delete_post");
+ nboard_thread_object_fields, thread, &data, &size);
if (ret != 0 || size == 0) {
warn("failed to marshall thread object during post delete");
return;
@@ -1008,11 +1032,14 @@ board_delete_post(struct session *s, struct board *boa
xfree(&post->body);
snprintf(del, sizeof(del), "[ Post deleted by %s ]",
s->user ? s->user->username : "unknown");
- post->body = xstrdup(del, "board_delete_post deleted body");
+ body = xstrdup(del);
+ if (body == NULL)
+ return;
+ post->body = body;
post->body_size = strlen(post->body) + 1;
ret = bile_marshall_object(board->bile, board_post_object_fields,
- nboard_post_object_fields, post, &data, &size, "board_delete_post");
+ nboard_post_object_fields, post, &data, &size);
if (ret != 0 || size == 0) {
warn("failed to marshall updated post object");
return;
@@ -1069,7 +1096,7 @@ board_index_sorted_post_ids(struct board *board,
};
struct board_fidonet_post fpost;
struct board_thread thread;
- size_t size, i, j, n, npost_ids, nthread_ids;
+ size_t ret, size, i, j, n, npost_ids, nthread_ids;
unsigned long *post_ids, *thread_ids, tmp_id;
struct board_id_time_map *id_map, *thread_map, tmp_map;
char *data;
@@ -1080,16 +1107,19 @@ board_index_sorted_post_ids(struct board *board,
if (npost_ids == 0)
goto write_out;
- id_map = xcalloc(sizeof(struct board_id_time_map),
- npost_ids, "board_id_time_map");
-
+ id_map = xcalloc(sizeof(struct board_id_time_map), npost_ids);
+ if (id_map == NULL)
+ goto write_out;
+
for (n = 0; n < npost_ids; n++) {
/* only read as far as the time */
- bile_read(board->bile, BOARD_FIDONET_POST_RTYPE,
+ ret = bile_read(board->bile, BOARD_FIDONET_POST_RTYPE,
post_ids[n], &fpost,
offsetof(struct board_fidonet_post, time) +
member_size(struct board_fidonet_post, time));
-
+ if (ret == 0)
+ goto write_out;
+
id_map[n].id = fpost.id;
id_map[n].time = fpost.time;
}
@@ -1116,16 +1146,20 @@ board_index_sorted_post_ids(struct board *board,
goto write_out;
thread_map = xcalloc(sizeof(struct board_id_time_map),
- nthread_ids, "board_id_time_map");
+ nthread_ids);
+ if (thread_map == NULL)
+ goto write_out;
npost_ids = 0;
for (n = 0; n < nthread_ids; n++) {
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
thread_ids[n], &data);
- bile_unmarshall_object(board->bile, board_thread_object_fields,
- nboard_thread_object_fields, data, size, &thread,
- sizeof(thread), false, "board_id_time_map");
+ ret = bile_unmarshall_object(board->bile,
+ board_thread_object_fields, nboard_thread_object_fields, data,
+ size, &thread, sizeof(thread), false);
xfree(&data);
+ if (ret == BILE_ERR_NO_MEMORY)
+ goto write_out;
thread_map[n].id = thread.thread_id;
thread_map[n].time = thread.last_post_at;
@@ -1146,16 +1180,22 @@ board_index_sorted_post_ids(struct board *board,
}
}
- post_ids = xcalloc(sizeof(long), npost_ids, "post_ids");
+ post_ids = xcalloc(sizeof(long), npost_ids);
+ if (post_ids == NULL)
+ goto write_out;
npost_ids = 0;
for (j = 0; j < nthread_ids; j++) {
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
thread_map[j].id, &data);
- bile_unmarshall_object(board->bile, board_thread_object_fields,
- nboard_thread_object_fields, data, size, &thread,
- sizeof(thread), true, "board_index_post_Ids");
+ if (data == NULL)
+ goto write_out;
+ ret = bile_unmarshall_object(board->bile,
+ board_thread_object_fields, nboard_thread_object_fields, data,
+ size, &thread, sizeof(thread), true);
xfree(&data);
+ if (ret == 0)
+ goto write_out;
/* these are already sorted, and we want to keep thread sort */
for (i = 0; i < thread.nposts; i++)