From 5395a7da901e4af9758762215b75d943ef253ef3 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Sat, 28 Sep 2024 00:30:09 +0200 Subject: check the memory limit and allow interruptions when loading files * Previously you could open files of arbitrary size and the limit would be checked only afterwards. * Many, but not all, cases should now be detected earlier. Since Scintilla allocates lots of memory as part of rendering, you can still run into memory limits even after successfully loading the file. * Loading extremely large files can also be potentially slow. Therefore, it is now possible to interrupt via CTRL+C. Again, if the UI is blocking because of stuff done as part of rendering, you still may not be able to interrupt the "blocking" operation. --- src/view.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/view.c b/src/view.c index 0d1d168..b70d9cd 100644 --- a/src/view.c +++ b/src/view.c @@ -45,6 +45,7 @@ #include "error.h" #include "qreg.h" #include "eol.h" +#include "memory.h" #include "view.h" /** @memberof teco_view_t */ @@ -216,8 +217,11 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro */ struct stat stat_buf = {.st_size = 0}; if (!fstat(g_io_channel_unix_get_fd(channel), &stat_buf) && - stat_buf.st_size > 0) + stat_buf.st_size > 0) { + if (!teco_memory_check(stat_buf.st_size, error)) + goto error; teco_view_ssm(ctx, SCI_ALLOCATE, stat_buf.st_size, 0); + } g_auto(teco_eol_reader_t) reader; teco_eol_reader_init_gio(&reader, channel); @@ -230,14 +234,24 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro teco_string_t str; GIOStatus rc = teco_eol_reader_convert(&reader, &str.data, &str.len, error); - if (rc == G_IO_STATUS_ERROR) { - teco_view_ssm(ctx, SCI_ENDUNDOACTION, 0, 0); - return FALSE; - } + if (rc == G_IO_STATUS_ERROR) + goto error; if (rc == G_IO_STATUS_EOF) break; teco_view_ssm(ctx, SCI_APPENDTEXT, str.len, (sptr_t)str.data); + + /* + * Even if we checked initially, knowing the file size, + * Scintilla could allocate much more bytes. + */ + if (!teco_memory_check(0, error)) + goto error; + + if (G_UNLIKELY(teco_interface_is_interrupted())) { + teco_error_interrupted_set(error); + goto error; + } } /* @@ -259,6 +273,10 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro teco_view_ssm(ctx, SCI_ENDUNDOACTION, 0, 0); return TRUE; + +error: + teco_view_ssm(ctx, SCI_ENDUNDOACTION, 0, 0); + return FALSE; } /** -- cgit v1.2.3