jcs
/subtext
/amendments
/220
*: Use NewPtr instead of malloc, add malloc and free debugging
Instead of free(ptr), use xfree(&ptr) and after it calls
DisposePtr(ptr), it will update ptr to point at NULL to catch
use-after-frees.
When MALLOC_DEBUG is defined, each allocation is added to a
list, and removed when freed. If it's not in the list at free
time, it's a double-free. Also, instead of pointing pointers at
NULL, point them to a pre-defined block of zeroes and in the
idle loop, periodically check that this block is still zero. This
will also catch use-after-frees in a more reliable (but costly)
way.
jcs made amendment 220 over 2 years ago
--- bile.c Tue Jul 19 13:30:56 2022
+++ bile.c Wed Jul 20 09:30:20 2022
@@ -81,7 +81,7 @@ bile_create(const Str255 filename, short vrefnum, cons
len = BILE_MAGIC_LEN;
tmp = xstrdup(BILE_MAGIC);
_bile_error = FSWrite(bile->frefnum, &len, tmp);
- free(tmp);
+ xfree(&tmp);
if (_bile_error)
goto create_bail;
@@ -103,7 +103,7 @@ bile_create(const Str255 filename, short vrefnum, cons
_bile_error = FSWrite(bile->frefnum, &len, tmp);
if (_bile_error)
goto create_bail;
- free(tmp);
+ xfree(&tmp);
GetFPos(fh, &bile->file_size);
@@ -117,7 +117,7 @@ create_bail:
FSClose(bile->frefnum);
bile->frefnum = -1;
if (bile != NULL)
- free(bile);
+ xfree(&bile);
return NULL;
}
@@ -195,7 +195,7 @@ open_bail:
FSClose(bile->frefnum);
bile->frefnum = -1;
if (bile != NULL)
- free(bile);
+ xfree(&bile);
return NULL;
}
@@ -262,7 +262,7 @@ bile_close(struct bile *bile)
FSClose(bile->frefnum);
bile->frefnum = -1;
if (bile->map != NULL)
- free(bile->map);
+ xfree(&bile->map);
}
struct bile_object *
@@ -898,7 +898,7 @@ bile_read_map(struct bile *bile, struct bile_object *m
map = xmalloczero(size);
_bile_error = FSRead(bile->frefnum, &size, map);
if (_bile_error) {
- free(map);
+ xfree(&map);
return -1;
}
@@ -975,7 +975,7 @@ bile_write_map(struct bile *bile)
}
/* successfully wrote new map, switch over */
- free(bile->map);
+ xfree(&bile->map);
bile->nobjects = new_nobjects;
bile->map = new_map;
bile->old_map_ptr.pos = bile->map_ptr.pos;
--- board.c Tue Jul 19 15:35:47 2022
+++ board.c Wed Jul 20 09:32:20 2022
@@ -166,7 +166,7 @@ board_show(struct session *s, short id)
while (!done && !s->ending) {
if (find_post_ids) {
if (post_ids != NULL) {
- free(post_ids);
+ xfree(&post_ids);
post_ids = NULL;
}
nall_post_ids = board_find_post_ids(board, &npost_ids,
@@ -261,7 +261,7 @@ handle_opt:
}
if (post_ids != NULL)
- free(post_ids);
+ xfree(&post_ids);
}
void
@@ -296,19 +296,19 @@ board_list_posts(struct session *s, struct board *boar
&data);
bile_unmarshall_object(board->bile, board_post_object_fields,
nboard_post_object_fields, data, size, &post, false);
- free(data);
+ xfree(&data);
if (post.thread_id != thread.thread_id) {
if (thread.thread_id) {
- free(thread.subject);
- free(thread.post_ids);
- free(thread.parent_post_ids);
+ xfree(&thread.subject);
+ xfree(&thread.post_ids);
+ xfree(&thread.parent_post_ids);
}
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
post.thread_id, &data);
bile_unmarshall_object(board->bile, board_thread_object_fields,
nboard_thread_object_fields, data, size, &thread, true);
- free(data);
+ xfree(&data);
for (j = 0; j < nitems(indent_parent_ids); j++)
indent_parent_ids[j] = 0;
@@ -358,11 +358,11 @@ board_list_posts(struct session *s, struct board *boar
session_flush(s);
if (thread.subject != NULL)
- free(thread.subject);
+ xfree(&thread.subject);
if (thread.post_ids != NULL)
- free(thread.post_ids);
+ xfree(&thread.post_ids);
if (thread.parent_post_ids != NULL)
- free(thread.parent_post_ids);
+ xfree(&thread.parent_post_ids);
}
unsigned long
@@ -413,7 +413,7 @@ post_compose_start:
tmp = session_field_input(s, 100, 50, thread->subject,
false, 0);
if (thread->subject != NULL)
- free(thread->subject);
+ xfree(&thread->subject);
thread->subject = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -427,7 +427,7 @@ post_compose_start:
session_printf(s, "{{B}}Error:{{/B}} Subject "
"cannot be blank (^C to cancel)\r\n");
session_flush(s);
- free(thread->subject);
+ xfree(&thread->subject);
continue;
}
thread->subject_size = strlen(thread->subject) + 1;
@@ -442,7 +442,7 @@ post_compose_start:
tmp = session_field_input(s, 2048, s->terminal_columns - 1,
post.body, true, 0);
if (post.body != NULL)
- free(post.body);
+ xfree(&post.body);
post.body = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -453,7 +453,7 @@ post_compose_start:
rtrim(post.body, "\r\n\t ");
if (post.body[0] == '\0') {
- free(post.body);
+ xfree(&post.body);
goto post_compose_done;
}
post.body_size = strlen(post.body) + 1;
@@ -514,11 +514,11 @@ post_compose_error:
post_compose_done:
if (parent_post == NULL) {
if (thread->subject != NULL)
- free(thread->subject);
- free(thread);
+ xfree(&thread->subject);
+ xfree(&thread);
}
if (post.body)
- free(post.body);
+ xfree(&post.body);
return post.id;
}
@@ -554,7 +554,7 @@ board_post_read(struct session *s, struct board *board
bile_error(board->bile));
bile_unmarshall_object(board->bile, board_post_object_fields,
nboard_post_object_fields, data, size, &post, true);
- free(data);
+ xfree(&data);
size = bile_read_alloc(board->bile, BOARD_THREAD_RTYPE,
post.thread_id, &data);
@@ -563,7 +563,7 @@ board_post_read(struct session *s, struct board *board
bile_error(board->bile));
bile_unmarshall_object(board->bile, board_thread_object_fields,
nboard_thread_object_fields, data, size, &thread, true);
- free(data);
+ xfree(&data);
dopts = xmalloc(sizeof(opts));
memcpy(dopts, opts, sizeof(opts));
@@ -694,8 +694,8 @@ board_find_post_ids(struct board *board, size_t *npost
bile_read_alloc(board->bile, BOARD_THREAD_RTYPE, o->id, &data);
bile_unmarshall_object(board->bile, board_thread_object_fields,
nboard_thread_object_fields, data, o->size, &thread, false);
- free(data);
- free(o);
+ xfree(&data);
+ xfree(&o);
thread_map[n].id = thread.thread_id;
thread_map[n].time = thread.last_post_at;
@@ -724,7 +724,7 @@ board_find_post_ids(struct board *board, size_t *npost
thread_map[j].id, &data);
bile_unmarshall_object(board->bile, board_thread_object_fields,
nboard_thread_object_fields, data, size, &thread, true);
- free(data);
+ xfree(&data);
for (i = 0; i < thread.nposts; i++) {
if (offset > 0 && seen_posts++ < offset)
@@ -740,8 +740,8 @@ board_find_post_ids(struct board *board, size_t *npost
break;
}
- free(thread.post_ids);
- free(thread.subject);
+ xfree(&thread.post_ids);
+ xfree(&thread.subject);
if (*npost_ids >= limit)
break;
@@ -749,7 +749,7 @@ board_find_post_ids(struct board *board, size_t *npost
done:
if (thread_map != NULL)
- free(thread_map);
+ xfree(&thread_map);
return nall_post_ids;
}
@@ -783,7 +783,7 @@ board_post_create(struct board *board, struct board_th
size) != size) {
warn("bile_write of new post failed! %d", bile_error(board->bile));
post->id = 0;
- free(data);
+ xfree(&data);
goto done;
}
@@ -829,7 +829,7 @@ board_post_create(struct board *board, struct board_th
post->id = 0;
goto done;
}
- free(data);
+ xfree(&data);
bile_flush(board->bile, true);
@@ -886,9 +886,9 @@ board_delete_post(struct session *s, struct board *boa
thread->nposts--;
- free(thread->post_ids);
+ xfree(&thread->post_ids);
thread->post_ids = new_post_ids;
- free(thread->parent_post_ids);
+ xfree(&thread->parent_post_ids);
thread->parent_post_ids = new_parent_post_ids;
ret = bile_marshall_object(board->bile, board_thread_object_fields,
@@ -901,10 +901,10 @@ board_delete_post(struct session *s, struct board *boa
data, size) != size) {
warn("bile_write of updated thread after post delete failed! "
"%d", bile_error(board->bile));
- free(data);
+ xfree(&data);
return;
}
- free(data);
+ xfree(&data);
bile_delete(board->bile, BOARD_POST_RTYPE, post->id);
@@ -914,7 +914,7 @@ board_delete_post(struct session *s, struct board *boa
/* all we can do is change the post to say deleted */
if (post->body != NULL)
- free(post->body);
+ xfree(&post->body);
snprintf(del, sizeof(del), "[ Post deleted by %s ]",
s->user ? s->user->username : "unknown");
post->body = xstrdup(del);
@@ -930,7 +930,7 @@ board_delete_post(struct session *s, struct board *boa
size) != size) {
warn("bile_write of updated post failed! %d",
bile_error(board->bile));
- free(data);
+ xfree(&data);
return;
}
}
--- chat.c Sat Jul 16 14:50:15 2022
+++ chat.c Wed Jul 20 09:32:36 2022
@@ -198,7 +198,7 @@ chat_start(struct session *s, char *with_node)
if (strcmp(input, "/quit") == 0 ||
strcmp(input, "/exit") == 0 ||
strcmp(input, "/leave") == 0) {
- free(input);
+ xfree(&input);
break;
} else if (strcmp(input, "/help") == 0) {
chat_help(s);
@@ -220,7 +220,7 @@ chat_start(struct session *s, char *with_node)
session_flush(s);
}
- free(input);
+ xfree(&input);
}
session_log(s, "Left chat with %s", with_node[0] ? with_node :
--- console.c Sat Jul 16 23:05:59 2022
+++ console.c Wed Jul 20 12:56:21 2022
@@ -72,7 +72,7 @@ console_init(void)
console->session = session_create("console", "console",
&console_node_funcs);
if (console->session == NULL) {
- free(console);
+ xfree(&console);
warn("No free nodes for a console");
return NULL;
}
@@ -118,7 +118,7 @@ console_init(void)
if ((sysop_username = user_first_sysop_username()) != NULL) {
strlcpy(console->session->autologin_username, sysop_username,
sizeof(console->session->autologin_username));
- free(sysop_username);
+ xfree(&sysop_username);
}
return console;
@@ -337,7 +337,7 @@ console_close_from_session(struct session *session)
struct console *console = (struct console *)session->cookie;
session_log(session, "Closing console session");
destroy_focusable(console->focusable);
- free(console);
+ xfree(&console);
}
short
--- db.c Wed Jul 13 17:45:43 2022
+++ db.c Wed Jul 20 09:34:13 2022
@@ -202,7 +202,7 @@ db_init(Str255 path, short vrefnum, struct bile *bile)
if (db_migrate(tdb, was_new) != 0) {
bile_close(tdb->bile);
- free(tdb);
+ xfree(&tdb);
return NULL;
}
@@ -232,12 +232,12 @@ void
db_close(struct db *tdb)
{
bile_close(tdb->bile);
- free(tdb->bile);
+ xfree(&tdb->bile);
if (tdb->sessions_bile != NULL) {
bile_close(tdb->sessions_bile);
- free(tdb->sessions_bile);
+ xfree(&tdb->sessions_bile);
}
- free(tdb);
+ xfree(&tdb);
}
short
@@ -309,7 +309,7 @@ db_migrate(struct db *tdb, short is_new)
user.is_enabled = DB_TRUE;
bile_write(tdb->bile, DB_USER_RTYPE, o->id, (char *)&user,
sizeof(user));
- free(o);
+ xfree(&o);
nuser++;
}
break;
@@ -424,7 +424,7 @@ db_config_load(struct db *tdb)
rlen, sizeof(tdb->config));
memcpy(&tdb->config, newconfig, sizeof(tdb->config));
- free(newconfig);
+ xfree(&newconfig);
}
void
@@ -442,7 +442,7 @@ db_cache_boards(struct db *tdb)
if (tdb->boards[n].bile)
bile_close(tdb->boards[n].bile);
}
- free(tdb->boards);
+ xfree(&tdb->boards);
}
if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename,
@@ -470,10 +470,10 @@ db_cache_boards(struct db *tdb)
bile_unmarshall_object(tdb->bile, board_object_fields,
nboard_object_fields, data, size, (char *)(&tdb->boards[n]),
true);
- free(data);
+ xfree(&data);
}
- free(ids);
+ xfree(&ids);
for (n = 0; n < tdb->nboards; n++) {
snprintf((char *)board_filename, sizeof(board_filename),
@@ -527,7 +527,7 @@ db_board_create(struct db *tdb, struct board *board)
if (bile_write(tdb->bile, DB_BOARD_RTYPE, board->id, data,
size) != size)
panic("save of new board failed: %d", bile_error(tdb->bile));
- free(data);
+ xfree(&data);
if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename,
false) != 0)
@@ -561,7 +561,7 @@ db_cache_folders(struct db *tdb)
if (tdb->folders[n].bile)
bile_close(tdb->folders[n].bile);
}
- free(tdb->folders);
+ xfree(&tdb->folders);
}
if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename,
@@ -588,10 +588,10 @@ db_cache_folders(struct db *tdb)
bile_unmarshall_object(tdb->bile, folder_object_fields,
nfolder_object_fields, data, size, (char *)(&tdb->folders[n]),
true);
- free(data);
+ xfree(&data);
}
- free(ids);
+ xfree(&ids);
for (n = 0; n < tdb->nfolders; n++) {
snprintf((char *)folder_filename, sizeof(folder_filename),
@@ -656,7 +656,7 @@ db_folder_create(struct db *tdb, struct folder *folder
if (bile_write(tdb->bile, DB_FOLDER_RTYPE, folder->id, data,
size) != size)
panic("save of new folder failed: %d", bile_error(tdb->bile));
- free(data);
+ xfree(&data);
if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename,
false) != 0)
--- focusable.c Wed Jun 1 16:40:57 2022
+++ focusable.c Wed Jul 20 09:34:25 2022
@@ -96,7 +96,7 @@ destroy_focusable(struct focusable *focusable)
if (nfocusables)
focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables);
else {
- free(focusables);
+ xfree(&focusables);
focusables = NULL;
}
--- folder.c Tue Jul 19 15:36:09 2022
+++ folder.c Wed Jul 20 22:18:54 2022
@@ -289,7 +289,7 @@ handle_opt:
}
}
- free(file_ids);
+ xfree(&file_ids);
}
void
@@ -327,7 +327,7 @@ folder_list_files(struct session *s, struct folder *fo
file_ids[off + n], &data);
bile_unmarshall_object(folder->bile, folder_file_object_fields,
nfolder_file_object_fields, data, size, &file, false);
- free(data);
+ xfree(&data);
strftime(time, sizeof(time), "%Y-%m-%d", localtime(&file.time));
@@ -424,7 +424,7 @@ folder_upload(struct session *s, struct folder *folder
session_pause_return(s, CONTROL_C, "to continue...");
ZDestroy(zs);
zs = NULL;
- free(upload_path);
+ xfree(&upload_path);
return 0;
}
@@ -471,7 +471,7 @@ folder_upload(struct session *s, struct folder *folder
}
if (fp)
fclose(fp);
- free(data);
+ xfree(&data);
SHA1End(&sha1, (char *)&file.sha1_checksum);
session_printf(s, "done.\r\n\r\n");
@@ -495,7 +495,7 @@ file_upload_annotate:
if (tmp == NULL)
goto file_upload_cancel;
strlcpy(file.filename, tmp, sizeof(file.filename));
- free(tmp);
+ xfree(&tmp);
session_output(s, "\r\n", 2);
session_flush(s);
@@ -503,7 +503,7 @@ file_upload_annotate:
if (!folder_file_valid_filename(s, folder, &file, &errorstr)) {
session_printf(s, "{{B}}Error:{{/B}} %s\r\n", errorstr);
- free(errorstr);
+ xfree(&errorstr);
continue;
}
@@ -519,7 +519,7 @@ file_upload_annotate:
if (tmp == NULL)
goto file_upload_cancel;
strlcpy(file.description, tmp, sizeof(file.description));
- free(tmp);
+ xfree(&tmp);
session_output(s, "\r\n", 2);
session_flush(s);
@@ -543,7 +543,7 @@ file_upload_annotate:
tmp = session_field_input(s, 2048, s->terminal_columns - 1,
file.notes, true, 0);
if (file.notes != NULL)
- free(file.notes);
+ xfree(&file.notes);
file.notes = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -555,7 +555,7 @@ file_upload_annotate:
rtrim(file.notes, "\r\n\t ");
if (file.notes[0] == '\0') {
- free(file.notes);
+ xfree(&file.notes);
file.notes = NULL;
file.notes_size = 0;
break;
@@ -636,9 +636,9 @@ file_upload_cancel:
file_upload_done:
if (file.notes)
- free(file.notes);
+ xfree(&file.notes);
if (upload_path != NULL)
- free(upload_path);
+ xfree(&upload_path);
return file.id;
}
@@ -675,7 +675,7 @@ folder_file_view(struct session *s, struct folder *fol
bile_error(folder->bile));
bile_unmarshall_object(folder->bile, folder_file_object_fields,
nfolder_file_object_fields, data, size, &file, true);
- free(data);
+ xfree(&data);
dopts = xmalloc(sizeof(opts));
memcpy(dopts, opts, sizeof(opts));
@@ -731,7 +731,7 @@ folder_file_view(struct session *s, struct folder *fol
folder->name, path);
session_printf(s,
"{{B}}Error:{{/B}} Failed opening file\r\n");
- free(path);
+ xfree(&path);
break;
}
@@ -769,7 +769,7 @@ folder_file_view(struct session *s, struct folder *fol
}
ZDestroy(zs);
zs = NULL;
- free(path);
+ xfree(&path);
session_printf(s, "\r\n");
session_flush(s);
@@ -848,8 +848,7 @@ folder_find_file_ids(struct folder *folder, size_t *nf
struct file_name_map {
unsigned long id;
char filename[10]; /* only sorted to 10 character places */
- };
- struct file_name_map *name_map = NULL, tmp_map;
+ } *name_map = NULL, tmp_map;
size_t n, size;
short i, j;
char *data;
@@ -867,8 +866,8 @@ folder_find_file_ids(struct folder *folder, size_t *nf
bile_read_alloc(folder->bile, FOLDER_FILE_RTYPE, o->id, &data);
bile_unmarshall_object(folder->bile, folder_file_object_fields,
nfolder_file_object_fields, data, o->size, &file, false);
- free(data);
- free(o);
+ xfree(&data);
+ xfree(&o);
name_map[n].id = file.id;
strlcpy(name_map[n].filename, file.filename,
@@ -920,10 +919,10 @@ folder_file_save(struct folder *folder, struct folder_
size) != size) {
warn("bile_write of new file failed! %d", bile_error(folder->bile));
file->id = 0;
- free(data);
+ xfree(&data);
return false;
}
- free(data);
+ xfree(&data);
bile_flush(folder->bile, true);
@@ -939,11 +938,11 @@ folder_file_save(struct folder *folder, struct folder_
warn("FSRename(%s, 0, %s) failed: %d", temp_path, new_name, ret);
bile_delete(folder->bile, FOLDER_FILE_RTYPE, file->id);
file->id = 0;
- free(new_name);
+ xfree(&new_name);
return false;
}
- free(new_name);
+ xfree(&new_name);
return true;
}
@@ -967,9 +966,9 @@ folder_delete_file(struct session *s, struct folder *f
session_log(s, "[%s] Failed deleting %s: %d", folder->name,
path, ret);
- free(path);
+ xfree(&path);
if (file->notes != NULL)
- free(file->notes);
+ xfree(&file->notes);
session_log(s, "[%s] Deleted file %s (%ld)", folder->name,
file->filename, file->id);
@@ -1024,15 +1023,15 @@ folder_file_valid_filename(struct session *session,
for (n = 0; o = bile_get_nth_of_type(folder->bile, n,
FOLDER_FILE_RTYPE); n++) {
if (o->id == file->id) {
- free(o);
+ xfree(&o);
continue;
}
bile_read_alloc(folder->bile, FOLDER_FILE_RTYPE, o->id, &data);
bile_unmarshall_object(folder->bile, folder_file_object_fields,
nfolder_file_object_fields, data, o->size, &tfile, false);
- free(data);
- free(o);
+ xfree(&data);
+ xfree(&o);
if (strcasecmp(file->filename, tfile.filename) == 0) {
*error = xstrdup("filename is already taken");
--- mail.c Tue Jul 19 15:36:51 2022
+++ mail.c Wed Jul 20 09:37:20 2022
@@ -69,11 +69,11 @@ void
mail_free_message_strings(struct mail_message *msg)
{
if (msg->subject != NULL) {
- free(msg->subject);
+ xfree(&msg->subject);
msg->subject = NULL;
}
if (msg->body != NULL) {
- free(msg->body);
+ xfree(&msg->body);
msg->body = NULL;
}
}
@@ -104,13 +104,13 @@ get_id:
if (sscanf(tmp, "%d", &ret) != 1 || ret < 1 || ret > nmsgs) {
session_printf(s, "{{B}}Invalid message ID{{/B}} (^C to cancel)\r\n");
session_flush(s);
- free(tmp);
+ xfree(&tmp);
goto get_id;
}
get_id_done:
if (tmp != NULL)
- free(tmp);
+ xfree(&tmp);
return ret;
}
@@ -147,7 +147,7 @@ mail_menu(struct session *s)
while (!done && !s->ending) {
if (find_message_ids) {
if (mail_ids != NULL)
- free(mail_ids);
+ xfree(&mail_ids);
nmsgs = mail_find_ids_for_user(s->user, &nmail_ids, &mail_ids,
page * MSGS_PER_PAGE, MSGS_PER_PAGE, false);
/* ceil(nmsgs / MSGS_PER_PAGE) */
@@ -236,7 +236,7 @@ handle_opt:
}
if (mail_ids != NULL)
- free(mail_ids);
+ xfree(&mail_ids);
}
void
@@ -267,7 +267,7 @@ mail_compose_start:
tmp = session_field_input(s, DB_USERNAME_LENGTH + 1,
DB_USERNAME_LENGTH + 1, to_username, false, 0);
if (to_username != NULL)
- free(to_username);
+ xfree(&to_username);
to_username = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -279,12 +279,12 @@ mail_compose_start:
session_printf(s, "{{B}}Error:{{/B}}{{#}} No such user \"%s\" "
"(^C to cancel)\r\n", to_username);
session_flush(s);
- free(to_username);
+ xfree(&to_username);
to_username = NULL;
continue;
}
msg.recipient_user_id = to_user->id;
- free(to_user);
+ xfree(&to_user);
break;
}
@@ -294,7 +294,7 @@ mail_compose_start:
tmp = session_field_input(s, 50, 50, msg.subject, false, 0);
if (msg.subject != NULL)
- free(msg.subject);
+ xfree(&msg.subject);
msg.subject = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -308,7 +308,7 @@ mail_compose_start:
session_printf(s, "{{B}}Error:{{/B}} Subject cannot "
"be blank (^C to cancel)\r\n");
session_flush(s);
- free(msg.subject);
+ xfree(&msg.subject);
msg.subject = NULL;
continue;
}
@@ -324,7 +324,7 @@ mail_compose_start:
tmp = session_field_input(s, 2048, s->terminal_columns - 1,
msg.body, true, 0);
if (msg.body != NULL)
- free(msg.body);
+ xfree(&msg.body);
msg.body = tmp;
session_output(s, "\r\n", 2);
session_flush(s);
@@ -338,7 +338,7 @@ mail_compose_start:
session_printf(s, "{{B}}Error:{{/B}} Message cannot "
"be blank (^C to cancel)\r\n");
session_flush(s);
- free(msg.body);
+ xfree(&msg.body);
msg.body = NULL;
continue;
}
@@ -394,7 +394,7 @@ mail_compose_start:
mail_compose_done:
if (to_username != NULL)
- free(to_username);
+ xfree(&to_username);
mail_free_message_strings(&msg);
}
@@ -421,7 +421,7 @@ mail_list(struct session *s, size_t nmail_ids, unsigne
break;
bile_unmarshall_object(db->bile, mail_object_fields,
nitems(mail_object_fields), data, size, &msg, true);
- free(data);
+ xfree(&data);
user = user_find_username(msg.sender_user_id);
strftime(time, sizeof(time), "%b %d", localtime(&msg.time));
@@ -473,7 +473,7 @@ mail_read(struct session *s, unsigned long id, short i
bile_unmarshall_object(db->bile, mail_object_fields,
nitems(mail_object_fields), data, size, &msg, true);
- free(data);
+ xfree(&data);
sender = user_find_username(msg.sender_user_id);
recipient = user_find_username(msg.recipient_user_id);
@@ -522,7 +522,7 @@ mail_read(struct session *s, unsigned long id, short i
mail_compose(s, sender->username, reply_subject, NULL);
- free(reply_subject);
+ xfree(&reply_subject);
break;
case 'd':
if (bile_delete(db->bile, DB_MESSAGE_RTYPE, msg.id) == 0)
@@ -626,7 +626,7 @@ mail_find_ids_for_user(struct user *user, size_t *nmai
id = o->id;
bile_read(db->bile, DB_MESSAGE_RTYPE, id, (char *)&msg_user_id,
sizeof(msg_user_id));
- free(o);
+ xfree(&o);
if (msg_user_id != user->id)
continue;
@@ -671,7 +671,7 @@ mail_find_ids_for_user(struct user *user, size_t *nmai
if (nmail_ids != NULL)
*nmail_ids = 0;
if (mail_ids != NULL)
- free(*mail_ids);
+ xfree(&(*mail_ids));
} else {
if (mail_ids != NULL) {
for (j = offset, i = 0; j < nmsgs_for_user; j++, i++)
--- main.c Tue Jul 19 15:21:55 2022
+++ main.c Thu Jul 21 08:47:03 2022
@@ -121,6 +121,7 @@ main(void)
SystemTask();
if (!GetNextEvent(everyEvent, &event)) {
+ xfree_verify();
blanker_idle();
continue;
}
@@ -261,7 +262,7 @@ handle_menu(long menu_id)
vers_s = xmalloc(100);
sprintf(vers_s, "%s %s", PROGRAM_NAME, get_version(true));
note("%s", vers_s);
- free(vers_s);
+ xfree(&vers_s);
ret = true;
break;
@@ -292,7 +293,7 @@ handle_menu(long menu_id)
}
}
- free(tfocusables);
+ xfree(&tfocusables);
ExitToShell();
break;
}
--- session.c Tue Jul 19 16:09:43 2022
+++ session.c Wed Jul 20 17:05:44 2022
@@ -91,7 +91,7 @@ session_create(char *node, char *via, struct node_func
session = xmalloczero(sizeof(struct session));
session->uthread = uthread_add(session_run, session);
if (!session->uthread) {
- free(session);
+ xfree(&session);
return NULL;
}
@@ -350,7 +350,7 @@ session_close(struct session *session)
panic("session_close failed to find session to remove");
nsessions--;
- free(session);
+ xfree(&session);
logger_update_title();
}
@@ -498,7 +498,7 @@ session_output_view_or_printf(struct session *session,
o = bile_find(db->bile, DB_TEXT_TYPE, id);
if (o == NULL || o->size == 0) {
if (o)
- free(0);
+ xfree(&o);
if (format == NULL)
return 0;
@@ -513,17 +513,17 @@ session_output_view_or_printf(struct session *session,
view = xmalloc(o->size + 1);
size = bile_read_object(db->bile, o, view, o->size);
view[size] = '\0';
- free(o);
+ xfree(&o);
size = session_expand_template(session, view, &output);
if (!size) {
- free(view);
+ xfree(&view);
return 0;
}
size = session_output(session, output, size);
- free(output);
- free(view);
+ xfree(&output);
+ xfree(&view);
return size;
}
@@ -841,7 +841,7 @@ append_char:
}
field_input_bail:
- free(field);
+ xfree(&field);
return NULL;
}
@@ -873,7 +873,7 @@ session_login(struct session *s)
if (username[0] == '\0') {
n--;
- free(username);
+ xfree(&username);
username = NULL;
continue;
}
@@ -881,7 +881,7 @@ session_login(struct session *s)
if (strcmp(username, GUEST_USERNAME) == 0) {
session_log(s, "Successful guest login in as %s", username);
- free(username);
+ xfree(&username);
return AUTH_USER_GUEST;
}
@@ -889,7 +889,7 @@ session_login(struct session *s)
strcmp(username, "new") == 0) && db->config.open_signup) {
session_log(s, "Successful guest signup login in as %s",
username);
- free(username);
+ xfree(&username);
return AUTH_USER_SIGNUP;
} else {
user = user_find_by_username(username);
@@ -904,7 +904,7 @@ session_login(struct session *s)
if (s->autologin_username[0]) {
if (user) {
- free(username);
+ xfree(&username);
s->user = user;
session_log(s, "Automatically logged in as %s",
s->autologin_username);
@@ -943,12 +943,12 @@ session_login(struct session *s)
len = strlen(username);
memset(username, 0, len);
- free(username);
+ xfree(&username);
username = NULL;
len = strlen(password);
memset(password, 0, len);
- free(password);
+ xfree(&password);
password = NULL;
if (s->user) {
@@ -964,9 +964,9 @@ session_login(struct session *s)
login_bail:
if (username != NULL)
- free(username);
+ xfree(&username);
if (password != NULL)
- free(password);
+ xfree(&password);
if (!s->ban_node_source) {
if (session_idled_out(s)) {
session_printf(s, "\r\nLogin timed out after %d seconds\r\n",
@@ -990,12 +990,12 @@ session_expand_template(struct session *session, const
size_t tmpllen, retsize, retpos;
size_t vallen;
short n, invar = 0, varlen = 0, doif, sep;
- char *varseek, *curvarpos, *val;
+ char *varseek, *curvarpos, *val, *data;
bool end_expansion = false;
retsize = 0;
retpos = 0;
- *ret = NULL;
+ data = NULL;
tmpllen = strlen(tmpl);
for (n = 0; n < tmpllen; n++) {
@@ -1012,12 +1012,12 @@ session_expand_template(struct session *session, const
varlen = 0;
n++;
} else if (tmpl[n] == '\r' && tmpl[n + 1] != '\n') {
- EXPAND_TO_FIT(*ret, retsize, retpos, 2, 64);
- (*ret)[retpos++] = '\r';
- (*ret)[retpos++] = '\n';
+ EXPAND_TO_FIT(data, retsize, retpos, 2, 64);
+ data[retpos++] = '\r';
+ data[retpos++] = '\n';
} else {
- EXPAND_TO_FIT(*ret, retsize, retpos, 1, 64);
- (*ret)[retpos++] = tmpl[n];
+ EXPAND_TO_FIT(data, retsize, retpos, 1, 64);
+ data[retpos++] = tmpl[n];
}
continue;
@@ -1083,13 +1083,14 @@ expand_var:
}
if (vallen) {
- EXPAND_TO_FIT(*ret, retsize, retpos, vallen, 128);
- memcpy(*ret + retpos, val, vallen);
+ EXPAND_TO_FIT(data, retsize, retpos, vallen, 128);
+ memcpy(data + retpos, val, vallen);
retpos += vallen;
}
}
- (*ret)[retpos] = '\0';
+ data[retpos] = '\0';
+ *ret = data;
return retpos;
}
@@ -1235,7 +1236,7 @@ session_page_sysop(struct session *s)
page_done:
if (message != NULL)
- free(message);
+ xfree(&message);
}
void
@@ -1283,7 +1284,7 @@ session_recents(struct session *s)
session_flush(s);
session_pause_return(s, 0, NULL);
- free(ids);
+ xfree(&ids);
}
void
--- settings.c Tue Jul 19 15:37:11 2022
+++ settings.c Wed Jul 20 09:53:01 2022
@@ -174,7 +174,7 @@ get_input:
session_printf(s,
"%s is too long (%d max, ^C to cancel)", sf->name,
sf->max - 1);
- free(input);
+ xfree(&input);
goto get_input;
}
strlcpy(new_data + sf->off, input, sf->max);
@@ -203,14 +203,14 @@ get_input:
session_printf(s,
"%s must be at least %d (^C to cancel)\r\n", sf->name,
sf->min);
- free(input);
+ xfree(&input);
goto get_input;
}
if (lval > sf->max) {
session_printf(s,
"%s must be less than %d (^C to cancel)\r\n", sf->name,
sf->max);
- free(input);
+ xfree(&input);
goto get_input;
}
if (sf->type == CONFIG_TYPE_LONG) {
@@ -273,10 +273,10 @@ get_input:
if (input[0] == '\0') {
lval = 0;
- free(input);
+ xfree(&input);
} else {
lval = ip2long(input);
- free(input);
+ xfree(&input);
if (lval == 0) {
session_printf(s,
"Invalid IP address (^C to cancel)\r\n");
@@ -293,7 +293,7 @@ get_input:
}
if (input != NULL)
- free(input);
+ xfree(&input);
if (s->ending) {
any_changes = false;
goto done;
@@ -305,7 +305,7 @@ done:
*result = new_data;
return 0;
} else {
- free(new_data);
+ xfree(&(*new_data));
*result = NULL;
return -1;
}
@@ -379,7 +379,7 @@ view_editor_show(size_t id, char *title)
HLock(view_editor->te);
InvalRect(&(*(view_editor->te))->viewRect);
HUnlock(view_editor->te);
- free(view);
+ xfree(&view);
}
bounds.left = bounds.right;
@@ -540,5 +540,5 @@ view_editor_close(struct focusable *focusable, EventRe
TEDispose(view_editor->te);
destroy_focusable(focusable);
- free(view_editor);
+ xfree(&view_editor);
}
--- signup.c Tue Jul 19 15:54:17 2022
+++ signup.c Wed Jul 20 09:40:11 2022
@@ -56,7 +56,7 @@ signup(struct session *s)
if (!user_valid_username(NULL, username, &error)) {
session_printf(s, "{{B}}Error:{{/B}} %s\r\n", error);
- free(error);
+ xfree(&error);
continue;
}
@@ -76,7 +76,7 @@ signup(struct session *s)
if (password[0] == '\0') {
session_printf(s, "{{B}}Error:{{/B}} "
"Password cannot be blank\r\n");
- free(password);
+ xfree(&password);
continue;
}
@@ -93,8 +93,8 @@ signup(struct session *s)
if (strcmp(password_confirm, password) != 0) {
session_printf(s, "{{B}}Error:{{/B}} "
"Passwords do not match\r\n");
- free(password);
- free(password_confirm);
+ xfree(&password);
+ xfree(&password_confirm);
continue;
}
@@ -113,11 +113,11 @@ signup(struct session *s)
signup_done:
if (username != NULL)
- free(username);
+ xfree(&username);
if (password != NULL)
- free(password);
+ xfree(&password);
if (password_confirm != NULL)
- free(password_confirm);
+ xfree(&password_confirm);
return user;
}
--- sysop.c Wed Jul 13 09:53:41 2022
+++ sysop.c Wed Jul 20 09:41:03 2022
@@ -105,7 +105,7 @@ sysop_edit_settings(struct session *s)
session_log(s, "Changed BBS settings");
session_printf(s, "Successfully saved changes to BBS Settings, "
"restart to take effect\r\n");
- free(new_config);
+ xfree(&new_config);
}
void
@@ -133,7 +133,7 @@ sysop_edit_boards(struct session *s)
* list of boards may change
*/
if (dopts != NULL)
- free(dopts);
+ xfree(&dopts);
dopts = xmalloc(sizeof(opts) +
(db->nboards * sizeof(struct session_menu_option)));
for (n = 0; n < db->nboards; n++) {
@@ -160,7 +160,7 @@ sysop_edit_boards(struct session *s)
board, sizeof(struct board), (void *)&new_board,
"New Board", "Sysop:Boards:New");
if (ret != 0) {
- free(board);
+ xfree(&board);
continue;
}
@@ -170,8 +170,8 @@ sysop_edit_boards(struct session *s)
session_log(s, "Created new board %ld: %s", new_board->id,
new_board->name);
- free(board);
- free(new_board);
+ xfree(&board);
+ xfree(&new_board);
break;
case '0':
case '1':
@@ -206,11 +206,11 @@ sysop_edit_boards(struct session *s)
if (bile_write(db->bile, DB_BOARD_RTYPE, new_board->id,
data, size) != size)
panic("save of board failed: %d", bile_error(db->bile));
- free(data);
+ xfree(&data);
session_log(s, "Saved changes to board %ld: %s",
new_board->id, new_board->name);
- free(new_board);
+ xfree(&new_board);
break;
}
if (!found) {
@@ -253,7 +253,7 @@ sysop_edit_folders(struct session *s)
* list of boards may change
*/
if (dopts != NULL)
- free(dopts);
+ xfree(&dopts);
dopts = xmalloc(sizeof(opts) +
(db->nboards * sizeof(struct session_menu_option)));
for (n = 0; n < db->nfolders; n++) {
@@ -280,7 +280,7 @@ sysop_edit_folders(struct session *s)
folder, sizeof(struct folder), (void *)&new_folder,
"New Folder", "Sysop:Folders:New");
if (ret != 0) {
- free(folder);
+ xfree(&folder);
continue;
}
@@ -290,8 +290,8 @@ sysop_edit_folders(struct session *s)
session_log(s, "Created new folder %ld: %s", new_folder->id,
new_folder->name);
- free(folder);
- free(new_folder);
+ xfree(&folder);
+ xfree(&new_folder);
break;
case '0':
case '1':
@@ -327,11 +327,11 @@ sysop_edit_folders(struct session *s)
data, size) != size)
panic("save of folder failed: %d",
bile_error(db->bile));
- free(data);
+ xfree(&data);
session_log(s, "Saved changes to folder %ld: %s",
new_folder->id, new_folder->name);
- free(new_folder);
+ xfree(&new_folder);
break;
}
if (!found) {
@@ -471,7 +471,7 @@ handle_opt:
}
if (all_user_ids != NULL)
- free(all_user_ids);
+ xfree(&all_user_ids);
}
size_t
--- telnet.c Sun Jul 17 20:12:36 2022
+++ telnet.c Wed Jul 20 09:41:17 2022
@@ -197,7 +197,7 @@ telnet_atexit(void)
if (node->state > TELNET_PB_STATE_UNUSED)
_TCPRelease(&telnet_exit_pb, node->stream, nil, nil, false);
- free(node);
+ xfree(&node);
telnet_nodes[n] = NULL;
}
@@ -877,7 +877,7 @@ telnet_print_busy(struct telnet_node *node)
if (data[n] == '\r' && data[n + 1] != '\n')
node->obuf[olen++] = '\n';
}
- free(data);
+ xfree(&data);
}
node->tcp_wds[0].ptr = (Ptr)&node->obuf;
--- user.c Tue Jul 19 15:38:19 2022
+++ user.c Wed Jul 20 09:42:02 2022
@@ -52,7 +52,7 @@ user_cache_usernames(void)
size_t nuser, len;
if (db->username_cache != NULL)
- free(db->username_cache);
+ xfree(&db->username_cache);
db->nusers = bile_count_by_type(db->bile, DB_USER_RTYPE);
db->username_cache = xmalloczero(sizeof(struct username_cache) *
@@ -71,7 +71,7 @@ user_cache_usernames(void)
strncpy(muser->username, user.username, sizeof(muser->username));
- free(o);
+ xfree(&o);
nuser++;
}
}
@@ -109,7 +109,7 @@ user_find(unsigned long id)
sizeof(struct user));
user = xmalloczero(sizeof(struct user));
memcpy(user, data, sizeof(struct user));
- free(data);
+ xfree(&data);
return user;
}
@@ -173,7 +173,7 @@ user_authenticate(struct user *user, const char *passw
memset(&hash, 0, sizeof(hash));
memset(salted, 0, slen);
- free(salted);
+ xfree(&salted);
if (res == 0)
return AUTH_USER_OK;
@@ -205,7 +205,7 @@ user_set_password(struct user *user, const char *passw
memcpy(salted + sizeof(salt) - 1, password, plen);
SHA256Data((const u_int8_t *)salted, slen, hash);
memset(salted, 0, slen);
- free(salted);
+ xfree(&salted);
memcpy(&user->password_hash, &hash, sizeof(user->password_hash));
@@ -258,7 +258,7 @@ user_valid_username(struct user *user, char *username,
if ((ouser = user_find_by_username(username))) {
ouser_id = ouser->id;
- free(ouser);
+ xfree(&ouser);
if (user == NULL || ouser_id != user->id) {
*error = xstrdup("username is already in use");
@@ -294,7 +294,7 @@ user_first_sysop_username(void)
while ((o = bile_get_nth_of_type(db->bile, nuser, DB_USER_RTYPE))) {
len = bile_read(db->bile, DB_USER_RTYPE, o->id, (char *)&user,
sizeof(user));
- free(o);
+ xfree(&o);
if (user.is_sysop) {
ret = xstrdup(user.username);
break;
@@ -329,7 +329,7 @@ user_change_password(struct session *s, struct user *u
if (password[0] == '\0') {
session_printf(s, "{{B}}Error:{{/B}} "
"Password cannot be blank\r\n");
- free(password);
+ xfree(&password);
password = NULL;
continue;
}
@@ -346,9 +346,9 @@ user_change_password(struct session *s, struct user *u
if (strcmp(password_confirm, password) != 0) {
session_printf(s, "{{B}}Error:{{/B}} "
"Passwords do not match\r\n");
- free(password);
+ xfree(&password);
password = NULL;
- free(password_confirm);
+ xfree(&password_confirm);
password_confirm = NULL;
continue;
}
@@ -371,9 +371,9 @@ user_change_password(struct session *s, struct user *u
}
if (password != NULL)
- free(password);
+ xfree(&password);
if (password_confirm != NULL)
- free(password_confirm);
+ xfree(&password_confirm);
}
void
@@ -389,7 +389,7 @@ user_delete(struct user *user)
id = o->id;
bile_read(db->bile, DB_MESSAGE_RTYPE, id, (char *)&msg_user_id,
sizeof(msg_user_id));
- free(o);
+ xfree(&o);
if (msg_user_id != user->id) {
n++;
--- user_settings.c Tue Jul 19 15:38:50 2022
+++ user_settings.c Wed Jul 20 09:42:39 2022
@@ -94,7 +94,7 @@ get_terminal_size:
session_output(s, "\r\n", 2);
session_flush(s);
if (tsize[0] == '\0') {
- free(tsize);
+ xfree(&tsize);
return;
}
@@ -102,7 +102,7 @@ get_terminal_size:
session_printf(s, "Invalid response, must be in format %dx%d\r\n",
s->terminal_columns, s->terminal_lines);
session_flush(s);
- free(tsize);
+ xfree(&tsize);
goto get_terminal_size;
}
@@ -110,7 +110,7 @@ get_terminal_size:
session_printf(s, "Terminal too small, must be at least "
"%dx%d\r\n", MIN_TERMINAL_COLUMNS, MIN_TERMINAL_LINES);
session_flush(s);
- free(tsize);
+ xfree(&tsize);
goto get_terminal_size;
}
@@ -144,7 +144,7 @@ user_settings_username(struct session *s)
if (username[0] == '\0') {
session_printf(s, "{{B}}Error:{{/B}} "
"Username cannot be blank\r\n");
- free(username);
+ xfree(&username);
username = NULL;
continue;
}
@@ -154,8 +154,8 @@ user_settings_username(struct session *s)
if (user_valid_username(s->user, username, &error) != 1) {
session_printf(s, "{{B}}Error:{{/B}} %s\r\n", error);
- free(error);
- free(username);
+ xfree(&error);
+ xfree(&username);
username = NULL;
continue;
}
@@ -171,7 +171,7 @@ user_settings_username(struct session *s)
}
if (username != NULL)
- free(username);
+ xfree(&username);
}
void
--- util.c Fri Jul 15 23:23:30 2022
+++ util.c Wed Jul 20 15:46:16 2022
@@ -65,14 +65,36 @@ static const char progress_ditl[] = {
static Handle progress_ditl_h = NULL;
static DialogPtr progress_dialog = NULL;
+static TEHandle track_control_te = NULL;
+
enum {
STOP_ALERT,
CAUTION_ALERT,
NOTE_ALERT
};
-static TEHandle track_control_te = NULL;
+#ifdef MALLOC_DEBUG
+/*
+ * List of allocations, updated at xmalloc() and xfree(). If an address
+ * passed to xfree() isn't in the list, it indicates a double-free.
+ */
+#define MALLOC_MAP_SIZE 512
+struct malloc_map_e {
+ unsigned long addr;
+ unsigned long size;
+} malloc_map[MALLOC_MAP_SIZE];
+
+/*
+ * On xfree(&), the pointer will be updated to point here. xfree_verify()
+ * should be called periodically to detect any writes to it, indicating
+ * a use-after-free.
+ */
+#define MALLOC_UAF_SIZE 256
+static char malloc_uaf[MALLOC_UAF_SIZE];
+
+#endif
+
void vwarn(short alert_func, const char *format, va_list ap);
/*
@@ -87,34 +109,98 @@ util_init(void)
HLock(alert_ditl_h);
memcpy(*alert_ditl_h, alert_ditl, sizeof(alert_ditl));
HUnlock(alert_ditl_h);
+
+#ifdef MALLOC_DEBUG
+ memset(&malloc_map, 0, sizeof(malloc_map));
+ memset(&malloc_uaf, 0, sizeof(malloc_uaf));
+#endif
}
/*
* Memory functions
*/
-
+
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
void *
xmalloc(size_t size)
{
void *ptr;
-
+#ifdef MALLOC_DEBUG
+ unsigned short n;
+#endif
+
if (size == 0)
panic("xmalloc: zero size");
-
- ptr = malloc(size);
+
+ ptr = NewPtr(size);
if (ptr == NULL)
panic("xmalloc(%lu) failed", size);
-
+
+#ifdef MALLOC_DEBUG
+ for (n = 0; n <= MALLOC_MAP_SIZE; n++) {
+ if (n == MALLOC_MAP_SIZE)
+ panic("xmalloc(%lu): out of malloc map entries", size);
+ if (malloc_map[n].addr == 0) {
+ malloc_map[n].addr = (unsigned long)ptr;
+ malloc_map[n].size = size;
+ break;
+ }
+ }
+#endif
+
return ptr;
}
+void
+xfree(void *ptrptr)
+{
+ unsigned long *addr = (unsigned long *)ptrptr;
+ void *ptr = (void *)*addr;
+#ifdef MALLOC_DEBUG
+ unsigned long n;
+
+ for (n = 0; n <= MALLOC_MAP_SIZE; n++) {
+ if (n == MALLOC_MAP_SIZE)
+ panic("xfree(%lu): can't find %lu in alloc map, likely "
+ "double free()", *addr);
+ if (malloc_map[n].addr == *addr) {
+ malloc_map[n].addr = 0;
+ malloc_map[n].size = 0;
+ break;
+ }
+ }
+#endif
+
+ DisposePtr(ptr);
+
+#ifdef MALLOC_DEBUG
+ *addr = (unsigned long)&malloc_uaf;
+#else
+ *addr = 0L;
+#endif
+}
+
+#ifdef MALLOC_DEBUG
+void
+xfree_verify(void)
+{
+ size_t n;
+
+ for (n = 0; n < sizeof(malloc_uaf); n++)
+ if (malloc_uaf[0] != '\0')
+ panic("xfree_verify: use-after-free detected");
+}
+#endif
+
void *
xmalloczero(size_t size)
{
- void *ptr = xmalloc(size);
+ void *ptr;
+ ptr = xmalloc(size);
memset(ptr, 0, size);
-
+
return ptr;
}
@@ -123,10 +209,13 @@ xcalloc(size_t nmemb, size_t size)
{
void *ptr;
- ptr = calloc(nmemb, size);
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size)
+ panic("xcalloc(%lu, %lu) overflow", nmemb, size);
+ ptr = xmalloczero(nmemb * size);
if (ptr == NULL)
panic("xcalloc(%lu, %lu) failed", nmemb, size);
-
+
return ptr;
}
@@ -134,16 +223,29 @@ void *
xrealloc(void *src, size_t size)
{
void *ptr;
+ unsigned long n;
- ptr = realloc(src, size);
- if (ptr == NULL)
- panic("realloc(%lu) failed", size);
-
+ ptr = xmalloc(size);
+ if (src != NULL) {
+ memcpy(ptr, src, size);
+#ifdef MALLOC_DEBUG
+ for (n = 0; n <= MALLOC_MAP_SIZE; n++) {
+ if (n == MALLOC_MAP_SIZE)
+ panic("xrealloc(0x%lx, %lu): can't find in alloc map, "
+ "double-free or bogus pointer passed", src, size);
+ if (malloc_map[n].addr == (unsigned long)src) {
+ malloc_map[n].addr = 0;
+ malloc_map[n].size = 0;
+ break;
+ }
+ }
+#endif
+ DisposePtr(src);
+ }
+
return ptr;
}
-#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
-
void *
xreallocarray(void *optr, size_t nmemb, size_t size)
{
@@ -576,7 +678,7 @@ xGetStringAsLong(short id)
c = xGetStringAsChar(id);
r = atol(c);
- free(c);
+ xfree(&c);
return r;
}
@@ -623,7 +725,7 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
wdir.ioNamePtr = (StringPtr)name;
if (PBGetWDInfo(&wdir, 0) != noErr) {
warn("Failed looking up directory");
- free(name);
+ xfree(&name);
return 1;
}
@@ -633,13 +735,13 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
if (PBHGetVInfoSync((HParmBlkPtr)&wvol) != noErr) {
warn("Failed getting volume info");
- free(name);
+ xfree(&name);
return 1;
}
if (wvol.ioVSigWord != 0x4244) {
warn("Unknown filesystem type 0x%x", wvol.ioVSigWord);
- free(name);
+ xfree(&name);
return 1;
}
@@ -682,17 +784,17 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
}
} else if (retlen == 0) {
(*ret)[0] = 0;
- free(tmp);
- free(tmpret);
- free(name);
+ xfree(&tmp);
+ xfree(&tmpret);
+ xfree(&name);
return 0;
}
CtoPstr(tmpret);
memcpy(*ret, tmpret, sizeof(tmpret));
- free(tmp);
- free(tmpret);
- free(name);
+ xfree(&tmp);
+ xfree(&tmpret);
+ xfree(&name);
return 0;
}
@@ -706,7 +808,7 @@ stat(char *path, struct stat *sb)
ppath = xstrdup(path);
CtoPstr(ppath);
ret = FStat((unsigned char *)ppath, sb);
- free(ppath);
+ xfree(&ppath);
return ret;
}
@@ -861,7 +963,7 @@ copy_file_contents(short source_ref, short dest_ref)
break;
}
- free(buf);
+ xfree(&buf);
if (error && error != eofErr)
return error;
--- util.h Tue Jul 12 17:10:27 2022
+++ util.h Wed Jul 20 15:08:46 2022
@@ -21,6 +21,8 @@
#include <limits.h>
#include <time.h>
+#define MALLOC_DEBUG
+
#ifndef SIZE_MAX
#define SIZE_MAX ULONG_MAX
#endif
@@ -88,6 +90,8 @@ struct stat {
void util_init(void);
void * xmalloc(size_t);
+void xfree(void *ptrptr);
+void xfree_verify(void);
void * xmalloczero(size_t);
void * xcalloc(size_t, size_t);
void * xrealloc(void *src, size_t size);
--- zmodem.c Thu Jul 21 09:01:34 2022
+++ zmodem.c Thu Jul 21 09:02:46 2022
@@ -1614,6 +1614,6 @@ ZDestroy(struct zmodem_session *zs)
if (zs->file)
fclose(zs->file);
if (zs->upload_file_path)
- free(zs->upload_file_path);
- free(zs);
+ xfree(&zs->upload_file_path);
+ xfree(&zs);
}