Skip to content

Commit

Permalink
db: fix buffer overflow when (de)serializing mtime
Browse files Browse the repository at this point in the history
We attempted to read/write modification time with 8 bytes, even though
`time_t` wasn't guaranteed to be 8 bytes in size.

By storing always storing mtime in an `int64_t`, we avoid this issue.
  • Loading branch information
cboxdoerfer committed Aug 4, 2023
1 parent b833e51 commit 3d73bca
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/fsearch_database.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ db_load_entry_super_elements_from_memory(const uint8_t *data_block,

if ((index_flags & DATABASE_INDEX_FLAG_MODIFICATION_TIME) != 0) {
// mtime: modification time file/folder
time_t mtime = 0;
int64_t mtime = 0;
data_block = copy_bytes_and_return_new_src(&mtime, data_block, 8);

db_entry_set_mtime(entry, mtime);
Expand Down Expand Up @@ -759,7 +759,7 @@ db_save_entry_super_elements(FILE *fp,

if ((index_flags & DATABASE_INDEX_FLAG_MODIFICATION_TIME) != 0) {
// mtime: modification time of file/folder
const uint64_t mtime = db_entry_get_mtime(entry);
const int64_t mtime = db_entry_get_mtime(entry);
bytes_written += write_data_to_file(fp, &mtime, 8, 1, write_failed);
if (*write_failed == true) {
g_debug("[db_save] failed to save modification time");
Expand Down
6 changes: 3 additions & 3 deletions src/fsearch_database_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct FsearchDatabaseEntry {
FsearchDatabaseEntryFolder *parent;
char *name;
off_t size;
time_t mtime;
int64_t mtime;

// idx: index of this entry in the sorted list at pos DATABASE_INDEX_TYPE_NAME
uint32_t idx;
Expand Down Expand Up @@ -114,7 +114,7 @@ db_entry_append_full_path(FsearchDatabaseEntry *entry, GString *str) {
g_string_append(str, entry->name[0] == '\0' ? G_DIR_SEPARATOR_S : entry->name);
}

time_t
int64_t
db_entry_get_mtime(FsearchDatabaseEntry *entry) {
return entry ? entry->mtime : 0;
}
Expand Down Expand Up @@ -336,7 +336,7 @@ db_entry_compare_entries_by_name(FsearchDatabaseEntry **a, FsearchDatabaseEntry
}

void
db_entry_set_mtime(FsearchDatabaseEntry *entry, time_t mtime) {
db_entry_set_mtime(FsearchDatabaseEntry *entry, int64_t mtime) {
entry->mtime = mtime;
}

Expand Down
4 changes: 2 additions & 2 deletions src/fsearch_database_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void
db_entry_set_idx(FsearchDatabaseEntry *entry, uint32_t idx);

void
db_entry_set_mtime(FsearchDatabaseEntry *entry, time_t mtime);
db_entry_set_mtime(FsearchDatabaseEntry *entry, int64_t mtime);

void
db_entry_set_size(FsearchDatabaseEntry *entry, off_t size);
Expand Down Expand Up @@ -86,7 +86,7 @@ db_entry_append_path(FsearchDatabaseEntry *entry, GString *str);
void
db_entry_append_full_path(FsearchDatabaseEntry *entry, GString *str);

time_t
int64_t
db_entry_get_mtime(FsearchDatabaseEntry *entry);

off_t
Expand Down
2 changes: 1 addition & 1 deletion src/fsearch_database_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ db_view_entry_append_path_for_idx(FsearchDatabaseView *view, uint32_t idx, GStri
}
}

time_t
int64_t
db_view_entry_get_mtime_for_idx(FsearchDatabaseView *view, uint32_t idx) {
g_assert(view);

Expand Down
2 changes: 1 addition & 1 deletion src/fsearch_database_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ db_view_entry_get_path_full_for_idx(FsearchDatabaseView *view, uint32_t idx);
void
db_view_entry_append_path_for_idx(FsearchDatabaseView *view, uint32_t idx, GString *str);

time_t
int64_t
db_view_entry_get_mtime_for_idx(FsearchDatabaseView *view, uint32_t idx);

off_t
Expand Down
2 changes: 1 addition & 1 deletion src/fsearch_query_matchers.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ uint32_t
fsearch_query_matcher_date_modified(FsearchQueryNode *node, FsearchQueryMatchData *match_data) {
FsearchDatabaseEntry *entry = fsearch_query_match_data_get_entry(match_data);
if (entry) {
const time_t time = db_entry_get_mtime(entry);
const int64_t time = db_entry_get_mtime(entry);
return cmp_num(time, node);
}
return 0;
Expand Down
34 changes: 21 additions & 13 deletions src/fsearch_result_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ typedef struct {
char *size;
char *type;
char *extension;
char time[100];
char *time;
} DrawRowContext;

static void
Expand All @@ -143,6 +143,7 @@ draw_row_ctx_free(DrawRowContext *ctx) {
g_clear_pointer(&ctx->extension, g_free);
g_clear_pointer(&ctx->type, g_free);
g_clear_pointer(&ctx->size, g_free);
g_clear_pointer(&ctx->time, g_free);
for (uint32_t i = 0; i < NUM_DATABASE_INDEX_TYPES; i++) {
if (ctx->highlights[i]) {
g_clear_pointer(&ctx->highlights[i], pango_attr_list_unref);
Expand Down Expand Up @@ -170,6 +171,8 @@ draw_row_ctx_new(FsearchDatabaseView *view, uint32_t row, GdkWindow *bin_window,
bool ret = true;
db_view_lock(view);

g_autoptr(GDateTime) dtime = NULL;

const uint32_t num_items = db_view_get_num_entries(view);
if (row >= num_items) {
g_debug("[draw_row] row idx out of bound");
Expand Down Expand Up @@ -209,11 +212,14 @@ draw_row_ctx_new(FsearchDatabaseView *view, uint32_t row, GdkWindow *bin_window,
off_t size = db_view_entry_get_size_for_idx(view, row);
ctx->size = fsearch_file_utils_get_size_formatted(size, config->show_base_2_units);

const time_t mtime = db_view_entry_get_mtime_for_idx(view, row);
strftime(ctx->time,
100,
"%Y-%m-%d %H:%M", //"%Y-%m-%d %H:%M",
localtime(&mtime));
const int64_t mtime = db_view_entry_get_mtime_for_idx(view, row);
dtime = g_date_time_new_from_unix_local(mtime);
if (dtime) {
ctx->time = g_date_time_format(dtime, "%Y-%m-%d %H:%M");
}
else {
ctx->time = g_strdup(_("Date out of range"));
}

out:
db_view_unlock(view);
Expand Down Expand Up @@ -290,13 +296,15 @@ fsearch_result_view_query_tooltip(FsearchDatabaseView *view,
config->show_base_2_units);
break;
case DATABASE_INDEX_TYPE_MODIFICATION_TIME: {
const time_t mtime = db_view_entry_get_mtime_for_idx(view, row);
char mtime_formatted[100] = "";
strftime(mtime_formatted,
sizeof(mtime_formatted),
"%Y-%m-%d %H:%M", //"%Y-%m-%d %H:%M",
localtime(&mtime));
text = g_strdup(mtime_formatted);
const int64_t mtime = db_view_entry_get_mtime_for_idx(view, row);
g_autoptr(GDateTime) dtime = g_date_time_new_from_unix_local(mtime);
if (dtime) {
text = g_date_time_format(dtime, "%Y-%m-%d %H:%M");
}
else {
text = g_strdup(_("Date out of range"));
}

break;
}
default:
Expand Down

0 comments on commit 3d73bca

Please sign in to comment.