From f06d3c1625e11ba3383d383622ad84a399e710d7 Mon Sep 17 00:00:00 2001 From: vysheng Date: Fri, 10 Jan 2014 18:37:56 +0400 Subject: [PATCH] free->tfree. Memory checks, if compiled with -DDEBUG --- binlog.c | 34 +++++++++++------------- interface.c | 33 ++++++++++++----------- loop.c | 4 +-- main.c | 26 +++++++++--------- mtproto-client.c | 10 +++---- mtproto-common.c | 3 +-- mtproto-common.h | 2 +- net.c | 8 +++--- queries.c | 51 ++++++++++++++++++----------------- structures.c | 60 +++++++++++++++++++++-------------------- structures.h | 1 + tools.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- tools.h | 10 ++++++- tree.h | 2 +- 14 files changed, 195 insertions(+), 118 deletions(-) diff --git a/binlog.c b/binlog.c index 49dfee0..883f5d5 100644 --- a/binlog.c +++ b/binlog.c @@ -210,7 +210,7 @@ void replay_log_event (void) { U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0); } else { static char buf[100]; - sprintf (buf, "user#%d", U->user_id); + tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = create_print_name (U->id, "!", buf, 0, 0); } } @@ -266,7 +266,7 @@ void replay_log_event (void) { U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0); } else { static char buf[100]; - sprintf (buf, "user#%d", U->user_id); + tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = create_print_name (U->id, "!", buf, 0, 0); } } @@ -335,7 +335,7 @@ void replay_log_event (void) { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); assert (U); - if (U->user.phone) { free (U->user.phone); } + if (U->user.phone) { tfree_str (U->user.phone); } U->user.phone = fetch_str_dup (); } rptr = in_ptr; @@ -379,8 +379,8 @@ void replay_log_event (void) { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); assert (U); - if (U->user.real_first_name) { free (U->user.real_first_name); } - if (U->user.real_last_name) { free (U->user.real_last_name); } + if (U->user.real_first_name) { tfree_str (U->user.real_first_name); } + if (U->user.real_last_name) { tfree_str (U->user.real_last_name); } U->user.real_first_name = fetch_str_dup (); U->user.real_last_name = fetch_str_dup (); } @@ -397,13 +397,11 @@ void replay_log_event (void) { U->flags |= FLAG_DELETED; U->state = sc_deleted; if (U->nonce) { - memset (U->nonce, 0, 256); - free (U->nonce); + tfree_secure (U->nonce, 256); U->nonce = 0; } if (U->g_key) { - memset (U->g_key, 0, 256); - free (U->g_key); + tfree_secure (U->g_key, 256); U->g_key = 0; } } @@ -431,8 +429,8 @@ void replay_log_event (void) { if (Us) { U->print_name = create_print_name (id, "!", Us->user.first_name, Us->user.last_name, 0); } else { - static char buf[20]; - sprintf (buf, "user#%d", U->user_id); + static char buf[100]; + tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = create_print_name (id, "!", buf, 0, 0); } U->g_key = talloc (256); @@ -515,7 +513,7 @@ void replay_log_event (void) { case CODE_binlog_set_dh_params: rptr ++; { - if (encr_prime) { free (encr_prime); } + if (encr_prime) { tfree_str (encr_prime); } encr_root = *(rptr ++); encr_prime = talloc (256); memcpy (encr_prime, rptr, 256); @@ -599,7 +597,7 @@ void replay_log_event (void) { peer_t *_C = user_chat_get (MK_CHAT (fetch_int ())); assert (_C && (_C->flags & FLAG_CREATED)); struct chat *C = &_C->chat; - if (C->title) { free (C->title); } + if (C->title) { tfree_str (C->title); } C->title = fetch_str_dup (); C->print_title = create_print_name (C->id, C->title, 0, 0, 0); }; @@ -646,8 +644,8 @@ void replay_log_event (void) { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.user_list_version = *(rptr ++); + if (C->chat.user_list) { tfree (C->chat.user_list, 12 * C->chat.user_list_size); } C->chat.user_list_size = *(rptr ++); - if (C->chat.user_list) { free (C->chat.user_list); } C->chat.user_list = talloc (12 * C->chat.user_list_size); memcpy (C->chat.user_list, rptr, 12 * C->chat.user_list_size); rptr += 3 * C->chat.user_list_size; @@ -685,7 +683,7 @@ void replay_log_event (void) { assert (C->user_list[i].user_id != user); } C->user_list_size ++; - C->user_list = trealloc (C->user_list, 12 * C->user_list_size); + C->user_list = trealloc (C->user_list, 12 * C->user_list_size - 12, 12 * C->user_list_size); C->user_list[C->user_list_size - 1].user_id = user; C->user_list[C->user_list_size - 1].inviter_id = inviter; C->user_list[C->user_list_size - 1].date = date; @@ -715,7 +713,7 @@ void replay_log_event (void) { } assert (C->user_list[C->user_list_size - 1].user_id == user); C->user_list_size --; - C->user_list = trealloc (C->user_list, 12 * C->user_list_size); + C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size); C->user_list_version = version; } break; @@ -1026,7 +1024,7 @@ void replay_log_event (void) { M->id = *(rptr ++); if (message_get (M->id)) { free_message (M); - free (M); + tfree (M, sizeof (*M)); } else { message_insert_tree (M); message_add_peer (M); @@ -1046,7 +1044,7 @@ void replay_log_event (void) { message_remove_tree (M); message_del_peer (M); free_message (M); - free (M); + tfree (M, sizeof (*M)); } break; case CODE_update_user_photo: diff --git a/interface.c b/interface.c index c3b7cc6..53a245c 100644 --- a/interface.c +++ b/interface.c @@ -214,29 +214,29 @@ char *get_default_prompt (void) { if (in_chat_mode) { peer_t *U = user_chat_get (chat_mode_id); assert (U && U->print_name); - l += sprintf (buf + l, COLOR_RED "%.*s " COLOR_NORMAL, 100, U->print_name); + l += tsnprintf (buf + l, 999 - l, COLOR_RED "%.*s " COLOR_NORMAL, 100, U->print_name); } if (unread_messages || cur_uploading_bytes || cur_downloading_bytes) { - l += sprintf (buf + l, COLOR_RED "["); + l += tsnprintf (buf + l, 999 - l, COLOR_RED "["); int ok = 0; if (unread_messages) { - l += sprintf (buf + l, "%d unread", unread_messages); + l += tsnprintf (buf + l, 999 - l, "%d unread", unread_messages); ok = 1; } if (cur_uploading_bytes) { if (ok) { *(buf + l) = ' '; l ++; } ok = 1; - l += sprintf (buf + l, "%lld%%Up", 100 * cur_uploaded_bytes / cur_uploading_bytes); + l += tsnprintf (buf + l, 999 - l, "%lld%%Up", 100 * cur_uploaded_bytes / cur_uploading_bytes); } if (cur_downloading_bytes) { if (ok) { *(buf + l) = ' '; l ++; } ok = 1; - l += sprintf (buf + l, "%lld%%Down", 100 * cur_downloaded_bytes / cur_downloading_bytes); + l += tsnprintf (buf + l, 999 - l, "%lld%%Down", 100 * cur_downloaded_bytes / cur_downloading_bytes); } - l += sprintf (buf + l, "]" COLOR_NORMAL); + l += tsnprintf (buf + l, 999 - l, "]" COLOR_NORMAL); return buf; } - l += sprintf (buf + l, "%s", default_prompt); + l += tsnprintf (buf + l, 999 - l, "%s", default_prompt); return buf; } @@ -413,7 +413,7 @@ int complete_user_list (int index, const char *text, int len, char **R) { index ++; } if (index < peer_num) { - *R = tstrdup (Peers[index]->print_name); + *R = strdup (Peers[index]->print_name); return index; } else { return -1; @@ -426,7 +426,7 @@ int complete_chat_list (int index, const char *text, int len, char **R) { index ++; } if (index < peer_num) { - *R = tstrdup (Peers[index]->print_name); + *R = strdup (Peers[index]->print_name); return index; } else { return -1; @@ -439,7 +439,7 @@ int complete_encr_chat_list (int index, const char *text, int len, char **R) { index ++; } if (index < peer_num) { - *R = tstrdup (Peers[index]->print_name); + *R = strdup (Peers[index]->print_name); return index; } else { return -1; @@ -452,7 +452,7 @@ int complete_user_chat_list (int index, const char *text, int len, char **R) { index ++; } if (index < peer_num) { - *R = tstrdup (Peers[index]->print_name); + *R = strdup (Peers[index]->print_name); return index; } else { return -1; @@ -465,7 +465,7 @@ int complete_string_list (char **list, int index, const char *text, int len, cha index ++; } if (list[index]) { - *R = tstrdup (list[index]); + *R = strdup (list[index]); return index; } else { *R = 0; @@ -505,7 +505,7 @@ char *command_generator (const char *text, int state) { if (c) { rl_line_buffer[rl_point] = c; } return R; case 1: - index = complete_user_list (index, text, len, &R); + index = complete_user_list (index, text, len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; case 2: @@ -1095,7 +1095,10 @@ void print_start (void) { if (readline_active) { saved_point = rl_point; #ifdef READLINE_GNU - saved_line = rl_copy_text(0, rl_end); + saved_line = talloc (rl_end + 1); + saved_line[rl_end] = 0; + memcpy (saved_line, rl_line_buffer, rl_end); + rl_save_prompt(); rl_replace_line("", 0); #else @@ -1122,7 +1125,7 @@ void print_end (void) { #endif rl_point = saved_point; rl_redisplay(); - free(saved_line); + tfree_str (saved_line); } prompt_was = 0; } diff --git a/loop.c b/loop.c index 6742763..104c30a 100644 --- a/loop.c +++ b/loop.c @@ -510,7 +510,7 @@ int loop (void) { break; } printf ("Invalid code. Try again: "); - free (code); + tfree_str (code); } auth_state = 300; } else { @@ -556,7 +556,7 @@ int loop (void) { break; } printf ("Invalid code. Try again: "); - free (code); + tfree_str (code); } auth_state = 300; } diff --git a/main.c b/main.c index 56094cc..fa5178b 100644 --- a/main.c +++ b/main.c @@ -83,7 +83,7 @@ int allow_weak_random; void set_default_username (const char *s) { if (default_username) { - free (default_username); + tfree_str (default_username); } default_username = tstrdup (s); } @@ -143,7 +143,7 @@ char *get_home_directory (void) { char *get_config_directory (void) { char *config_directory; - assert (asprintf (&config_directory, "%s/" CONFIG_DIRECTORY, get_home_directory ()) >= 0); + tasprintf (&config_directory, "%s/" CONFIG_DIRECTORY, get_home_directory ()); return config_directory; } @@ -174,8 +174,8 @@ char *get_binlog_file_name (void) { char *make_full_path (char *s) { if (*s != '/') { char *t = s; - assert (asprintf (&s, "%s/%s", get_home_directory (), s) >= 0); - free (t); + tasprintf (&s, "%s/%s", get_home_directory (), s); + tfree_str (t); } return s; } @@ -189,7 +189,7 @@ void running_for_first_time (void) { if (config_filename) { return; // Do not create custom config file } - assert (asprintf (&config_filename, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, CONFIG_FILE) >= 0); + tasprintf (&config_filename, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, CONFIG_FILE); config_filename = make_full_path (config_filename); static struct stat config_file_stat; @@ -201,7 +201,7 @@ void running_for_first_time (void) { printf ("[%s] created\n", config_directory); } - free (config_directory); + tfree_str (config_directory); config_directory = NULL; // see if config file is there if (stat (config_filename, &config_file_stat) != 0) { @@ -246,13 +246,13 @@ void parse_config_val (config_t *conf, char **s, char *param_name, const char *d config_lookup_string (conf, buf, &r); if (r) { if (path) { - assert (asprintf (s, "%s/%s", path, r) >= 0); + tasprintf (s, "%s/%s", path, r); } else { *s = tstrdup (r); } } else { if (path) { - assert (asprintf (s, "%s/%s", path, default_name) >= 0); + tasprintf (s, "%s/%s", path, default_name); } else { *s = tstrdup (default_name); } @@ -316,11 +316,11 @@ void parse_config (void) { #else void parse_config (void) { printf ("libconfig not enabled\n"); - assert (asprintf (&auth_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, AUTH_KEY_FILE) >= 0); - assert (asprintf (&state_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, STATE_FILE) >= 0); - assert (asprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE) >= 0); - assert (asprintf (&downloads_directory, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, DOWNLOADS_DIRECTORY) >= 0); - assert (asprintf (&binlog_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, BINLOG_FILE) >= 0); + tasprintf (&auth_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, AUTH_KEY_FILE); + tasprintf (&state_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, STATE_FILE); + tasprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE); + tasprintf (&downloads_directory, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, DOWNLOADS_DIRECTORY); + tasprintf (&binlog_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, BINLOG_FILE); } #endif diff --git a/mtproto-client.c b/mtproto-client.c index 3fc865c..fb4103f 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -830,9 +830,9 @@ void work_update_binlog (void) { peer_t *UC = user_chat_get (user_id); if (UC) { struct user *U = &UC->user; - if (U->first_name) { free (U->first_name); } - if (U->last_name) { free (U->last_name); } - if (U->print_name) { free (U->print_name); } + if (U->first_name) { tfree_str (U->first_name); } + if (U->last_name) { tfree_str (U->last_name); } + if (U->print_name) { tfree_str (U->print_name); } U->first_name = fetch_str_dup (); U->last_name = fetch_str_dup (); U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0); @@ -1199,8 +1199,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { s, location); pop_color (); print_end (); - free (s); - free (location); + tfree_str (s); + tfree_str (location); } break; case CODE_update_new_geo_chat_message: diff --git a/mtproto-common.c b/mtproto-common.c index 2d87f83..8175864 100644 --- a/mtproto-common.c +++ b/mtproto-common.c @@ -131,8 +131,7 @@ void prng_seed (const char *password_filename, int password_length) { } RAND_seed (a, s); BN_ctx = BN_CTX_new (); - memset (a, 0, s); - free (a); + tfree_secure (a, 64 + password_length); } int serialize_bignum (BIGNUM *b, char *buffer, int maxlen) { diff --git a/mtproto-common.h b/mtproto-common.h index 0b8bffd..0fda8c8 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -320,7 +320,7 @@ static inline int fetch_update_str (char **s) { int l = prefetch_strlen (); char *r = fetch_str (l); if (memcmp (*s, r, l) || (*s)[l]) { - free (*s); + tfree_str (*s); *s = talloc (l + 1); memcpy (*s, r, l); (*s)[l] = 0; diff --git a/net.c b/net.c index 3ecfa51..5d62e87 100644 --- a/net.c +++ b/net.c @@ -111,8 +111,8 @@ struct connection_buffer *new_connection_buffer (int size) { } void delete_connection_buffer (struct connection_buffer *b) { - free (b->start); - free (b); + tfree (b->start, b->end - b->start); + tfree (b, sizeof (*b)); } int write_out (struct connection *c, const void *data, int len) { @@ -250,7 +250,7 @@ struct connection *create_connection (const char *host, int port, struct session if (errno != EINPROGRESS) { logprintf ( "Can not connect to %s:%d %m\n", host, port); close (fd); - free (c); + tfree (c, sizeof (*c)); return 0; } } @@ -268,7 +268,7 @@ struct connection *create_connection (const char *host, int port, struct session } logprintf ("Connect with %s:%d timeout\n", host, port); close (fd); - free (c); + tfree (c, sizeof (*c)); return 0; } diff --git a/queries.c b/queries.c index 7eaff00..3fbfb24 100644 --- a/queries.c +++ b/queries.c @@ -191,8 +191,8 @@ void query_error (long long id) { } else { logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); } - free (q->data); - free (q); + tfree (q->data, q->data_len * 4); + tfree (q, sizeof (*q)); } queries_num --; } @@ -255,8 +255,8 @@ void query_result (long long id UU) { q->methods->on_answer (q); assert (in_ptr == in_end); } - free (q->data); - free (q); + tfree (q->data, 4 * q->data_len); + tfree (q, sizeof (*q)); } if (end) { in_ptr = end; @@ -326,7 +326,7 @@ void do_insert_header (void) { uname (&st); out_string (st.machine); static char buf[65536]; - sprintf (buf, "%999s %999s %999s", st.sysname, st.release, st.version); + tsnprintf (buf, 65535, "%999s %999s %999s", st.sysname, st.release, st.version); out_string (buf); out_string (TG_VERSION " (build " TG_BUILD ")"); out_string ("En"); @@ -399,7 +399,7 @@ int send_code_on_answer (struct query *q UU) { int l = prefetch_strlen (); char *s = fetch_str (l); if (phone_code_hash) { - free (phone_code_hash); + tfree_str (phone_code_hash); } phone_code_hash = strndup (s, l); want_dc_num = -1; @@ -933,7 +933,7 @@ void do_send_text (peer_id_t id, char *file_name) { int fd = open (file_name, O_RDONLY); if (fd < 0) { rprintf ("No such file '%s'\n", file_name); - free (file_name); + tfree_str (file_name); return; } static char buf[(1 << 20) + 1]; @@ -941,12 +941,12 @@ void do_send_text (peer_id_t id, char *file_name) { assert (x >= 0); if (x == (1 << 20) + 1) { rprintf ("Too big file '%s'\n", file_name); - free (file_name); + tfree_str (file_name); close (fd); } else { buf[x] = 0; do_send_message (id, buf, x); - free (file_name); + tfree_str (file_name); close (fd); } } @@ -1437,7 +1437,7 @@ void send_part (struct send_file *f) { MD5 (str, 64, md5); out_int ((*(int *)md5) ^ (*(int *)(md5 + 4))); - free (f->iv); + tfree_secure (f->iv, 32); M->media.encr_photo.key = f->key; M->media.encr_photo.iv = f->init_iv; @@ -1456,8 +1456,8 @@ void send_part (struct send_file *f) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M); } - free (f->file_name); - free (f); + tfree_str (f->file_name); + tfree (f, sizeof (*f)); } } @@ -1769,7 +1769,7 @@ void end_load (struct download *D) { logprintf ("Done: %s\n", D->name); } else if (D->next == 2) { static char buf[PATH_MAX]; - if (snprintf (buf, sizeof (buf), OPEN_BIN, D->name) >= (int) sizeof (buf)) { + if (tsnprintf (buf, sizeof (buf), OPEN_BIN, D->name) >= (int) sizeof (buf)) { logprintf ("Open image command buffer overflow\n"); } else { int x = system (buf); @@ -1780,10 +1780,10 @@ void end_load (struct download *D) { } } if (D->iv) { - free (D->iv); + tfree_secure (D->iv, 32); } - free (D->name); - free (D); + tfree_str (D->name); + tfree (D, sizeof (*D)); } void load_next_part (struct download *D); @@ -1832,9 +1832,9 @@ void load_next_part (struct download *D) { static char buf[PATH_MAX]; int l; if (!D->id) { - l = snprintf (buf, sizeof (buf), "%s/download_%lld_%d", get_downloads_directory (), D->volume, D->local_id); + l = tsnprintf (buf, sizeof (buf), "%s/download_%lld_%d", get_downloads_directory (), D->volume, D->local_id); } else { - l = snprintf (buf, sizeof (buf), "%s/download_%lld", get_downloads_directory (), D->id); + l = tsnprintf (buf, sizeof (buf), "%s/download_%lld", get_downloads_directory (), D->id); } if (l >= (int) sizeof (buf)) { logprintf ("Download filename is too long"); @@ -2027,7 +2027,7 @@ int import_auth_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_auth_authorization); fetch_int (); // expires fetch_alloc_user (); - free (export_auth_str); + tfree_str (export_auth_str); export_auth_str = 0; return 0; } @@ -2353,8 +2353,7 @@ void do_create_keys_end (struct secret_chat *U) { U->state = sc_deleted; } - memset (t, 0, 256); - free (t); + tfree_secure (t, 256); BN_clear_free (p); BN_clear_free (g_b); @@ -2432,7 +2431,6 @@ void do_send_create_encr_chat (void *x, unsigned char *random) { int get_dh_config_on_answer (struct query *q UU) { unsigned x = fetch_int (); assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified || LOG_DH_CONFIG); - logprintf ("old = %d\n", encr_param_version); if (x == CODE_messages_dh_config || x == LOG_DH_CONFIG) { int a = fetch_int (); int l = prefetch_strlen (); @@ -2449,14 +2447,15 @@ int get_dh_config_on_answer (struct query *q UU) { if (x == LOG_DH_CONFIG) { return 0; } int l = prefetch_strlen (); assert (l == 256); - unsigned char *random = (void *)fetch_str_dup (); + unsigned char *random = talloc (256); + memcpy (random, fetch_str (256), 256); if (q->extra) { void **x = q->extra; ((void (*)(void *, void *))(*x))(x[1], random); - free (x); - free (random); + tfree (x, 2 * sizeof (void *)); + tfree_secure (random, 256); } else { - free (random); + tfree_secure (random, 256); } return 0; } diff --git a/structures.c b/structures.c index 2992fe7..0bde616 100644 --- a/structures.c +++ b/structures.c @@ -150,7 +150,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha int p = 0; for (i = 0; i < 4; i++) { if (d[i] && strlen (d[i])) { - p += snprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]); + p += tsnprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]); assert (p < 9990); } } @@ -177,7 +177,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha } cc ++; assert (cc <= 9999); - sprintf (s + fl, "#%d", cc); + tsnprintf (s + fl, 9999 - fl, "#%d", cc); } return tstrdup (s); } @@ -595,7 +595,7 @@ void fetch_chat_full (struct chat *C) { } if (version > 0) { bl_do_set_chat_participants (C, version, users_num, users); - free (users); + tfree (users, sizeof (struct chat_user) * users_num); } bl_do_set_chat_full_photo (C, start, 4 * (end - start)); } @@ -945,7 +945,9 @@ void fetch_message_media (struct message_media *M) { M->user_id = fetch_int (); break; case CODE_message_media_unsupported: - M->data = fetch_str_dup (); + M->data_size = prefetch_strlen (); + M->data = talloc (M->data_size); + memcpy (M->data, fetch_str (M->data_size), M->data_size); break; default: logprintf ("type = 0x%08x\n", M->type); @@ -1582,41 +1584,41 @@ struct user *fetch_alloc_user_full (void) { } void free_user (struct user *U) { - if (U->first_name) { free (U->first_name); } - if (U->last_name) { free (U->last_name); } - if (U->print_name) { free (U->print_name); } - if (U->phone) { free (U->phone); } + if (U->first_name) { tfree_str (U->first_name); } + if (U->last_name) { tfree_str (U->last_name); } + if (U->print_name) { tfree_str (U->print_name); } + if (U->phone) { tfree_str (U->phone); } } void free_photo_size (struct photo_size *S) { - free (S->type); + tfree_str (S->type); if (S->data) { - free (S->data); + tfree (S->data, S->size); } } void free_photo (struct photo *P) { if (!P->access_hash) { return; } - if (P->caption) { free (P->caption); } + if (P->caption) { tfree_str (P->caption); } if (P->sizes) { int i; for (i = 0; i < P->sizes_num; i++) { free_photo_size (&P->sizes[i]); } - free (P->sizes); + tfree (P->sizes, sizeof (struct photo_size) * P->sizes_num); } } void free_video (struct video *V) { if (!V->access_hash) { return; } - free (V->caption); + tfree_str (V->caption); free_photo_size (&V->thumb); } void free_document (struct document *D) { if (!D->access_hash) { return; } - free (D->caption); - free (D->mime_type); + tfree_str (D->caption); + tfree_str (D->mime_type); free_photo_size (&D->thumb); } @@ -1633,22 +1635,22 @@ void free_message_media (struct message_media *M) { free_video (&M->video); return; case CODE_message_media_contact: - free (M->phone); - free (M->first_name); - free (M->last_name); + tfree_str (M->phone); + tfree_str (M->first_name); + tfree_str (M->last_name); return; case CODE_message_media_document: free_document (&M->document); return; case CODE_message_media_unsupported: - free (M->data); + tfree (M->data, M->data_size); return; case CODE_decrypted_message_media_photo: case CODE_decrypted_message_media_video: case CODE_decrypted_message_media_audio: case CODE_decrypted_message_media_document: - free (M->encr_photo.key); - free (M->encr_photo.iv); + tfree_secure (M->encr_photo.key, 32); + tfree_secure (M->encr_photo.iv, 32); return; case 0: break; @@ -1663,11 +1665,11 @@ void free_message_action (struct message_action *M) { case CODE_message_action_empty: break; case CODE_message_action_chat_create: - free (M->title); - free (M->users); + tfree_str (M->title); + tfree (M->users, M->user_num * 4); break; case CODE_message_action_chat_edit_title: - free (M->new_title); + tfree_str (M->new_title); break; case CODE_message_action_chat_edit_photo: free_photo (&M->photo); @@ -1687,7 +1689,7 @@ void free_message_action (struct message_action *M) { void free_message (struct message *M) { if (!M->service) { - if (M->message) { free (M->message); } + if (M->message) { tfree_str (M->message); } free_message_media (&M->media); } else { free_message_action (&M->action); @@ -1808,7 +1810,7 @@ struct message *fetch_alloc_geo_message (void) { message_del_peer (M1); free_message (M1); memcpy (M1, M, sizeof (*M)); - free (M); + tfree (M, sizeof (*M)); message_add_use (M1); message_add_peer (M1); messages_allocated --; @@ -1904,12 +1906,12 @@ struct chat *fetch_alloc_chat_full (void) { } void free_chat (struct chat *U) { - if (U->title) { free (U->title); } - if (U->print_title) { free (U->print_title); } + if (U->title) { tfree_str (U->title); } + if (U->print_title) { tfree_str (U->print_title); } } int print_stat (char *s, int len) { - return snprintf (s, len, + return tsnprintf (s, len, "users_allocated\t%d\n" "chats_allocated\t%d\n" "secret_chats_allocated\t%d\n" diff --git a/structures.h b/structures.h index 7e316fe..264317f 100644 --- a/structures.h +++ b/structures.h @@ -298,6 +298,7 @@ struct message_media { struct encr_document encr_document; struct encr_file encr_file; void *data; + int data_size; }; }; diff --git a/tools.c b/tools.c index 748edd5..bc8597f 100644 --- a/tools.c +++ b/tools.c @@ -17,6 +17,8 @@ Copyright Vitaly Valtman 2013 */ +#define _GNU_SOURCE + #include #include #include @@ -26,21 +28,79 @@ #include "interface.h" #include "tools.h" + static void out_of_memory (void) { logprintf ("Out of memory\n"); assert (0 && "Out of memory"); } -void *trealloc (void *ptr, size_t size) { +int tsnprintf (char *buf, int len, const char *format, ...) { + va_list ap; + va_start (ap, format); + int r = vsnprintf (buf, len, format, ap); + va_end (ap); + assert (r <= len && "tsnprintf buffer overflow"); + return r; +} + +int tasprintf (char **res, const char *format, ...) { + va_list ap; + va_start (ap, format); + int r = vasprintf (res, format, ap); + assert (r >= 0); + va_end (ap); + void *rs = talloc (strlen (*res) + 1); + memcpy (rs, *res, strlen (*res) + 1); + free (*res); + *res = rs; + return r; +} + +void tfree (void *ptr, int size) { +#ifdef DEBUG + ptr -= 4; + assert (*(int *)ptr == (int)((size) ^ 0xbedabeda)); + assert (*(int *)(ptr + 4 + size) == (int)((size) ^ 0x0bed0bed)); + memset (ptr, 0, size + 8); +#endif + free (ptr); +} + +void tfree_str (void *ptr) { + if (!ptr) { return; } + tfree (ptr, strlen (ptr) + 1); +} + +void tfree_secure (void *ptr, int size) { + memset (ptr, 0, size); + tfree (ptr, size); +} + +void *trealloc (void *ptr, size_t old_size __attribute__ ((unused)), size_t size) { +#ifdef DEBUG + void *p = talloc (size); + memcpy (p, ptr, size >= old_size ? old_size : size); + tfree (ptr, old_size); + return p; +#else void *p = realloc (ptr, size); ensure_ptr (p); return p; +#endif } void *talloc (size_t size) { +#ifdef DEBUG + void *p = malloc (size + 8); + ensure_ptr (p); + *(int *)p = size ^ 0xbedabeda; + *(int *)(p + 4 + size) = size ^ 0x0bed0bed; + return p + 4; +#else void *p = malloc (size); ensure_ptr (p); return p; +#endif } void *talloc0 (size_t size) { @@ -50,11 +110,18 @@ void *talloc0 (size_t size) { } char *tstrdup (const char *s) { +#ifdef DEBUG + int l = strlen (s); + char *p = talloc (l + 1); + memcpy (p, s, l + 1); + return p; +#else char *p = strdup (s); if (p == NULL) { out_of_memory (); } return p; +#endif } void ensure (int r) { diff --git a/tools.h b/tools.h index 9753b86..66c6d96 100644 --- a/tools.h +++ b/tools.h @@ -21,10 +21,18 @@ #define __TOOLS_H__ void *talloc (size_t size); -void *trealloc (void *ptr, size_t size); +void *trealloc (void *ptr, size_t old_size, size_t size); void *talloc0 (size_t size); char *tstrdup (const char *s); void ensure (int r); void ensure_ptr (void *p); +void tfree (void *ptr, int size); +void tfree_str (void *ptr); +void tfree_secure (void *ptr, int size); + + +int tsnprintf (char *buf, int len, const char *format, ...) __attribute__ ((format (printf, 3, 4))); +int tasprintf (char **res, const char *format, ...) __attribute__ ((format (printf, 2, 3))); + #endif diff --git a/tree.h b/tree.h index f75449b..3de93aa 100644 --- a/tree.h +++ b/tree.h @@ -40,7 +40,7 @@ struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\ }\ \ void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\ - free (T);\ + tfree (T, sizeof (*T));\ }\ \ void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\