From 39d88e33aa2e7def9a99614659b4da9e858e83ba Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Fri, 2 Feb 2018 11:47:11 +0100 Subject: [PATCH 1/4] checksum remove UB on high chars --- src/core/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/settings.c b/src/core/settings.c index 3ebb9e4a..ba571e63 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -665,7 +665,7 @@ void sig_term(int n) would be nice but would just take more space without much real benefit */ static unsigned int file_checksum(const char *fname) { - char buf[512]; + unsigned char buf[512]; int f, ret, n; unsigned int checksum = 0; From 8a428d2df279b01589688c421826e54f78407e63 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sat, 3 Feb 2018 22:08:16 +0100 Subject: [PATCH 2/4] just use a real checksum --- src/core/settings.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index ba571e63..4484deaa 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -29,6 +29,7 @@ #include "settings.h" #include "default-config.h" +#include #include #define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */ @@ -47,7 +48,7 @@ static int timeout_tag; static int config_last_modifycounter; static time_t config_last_mtime; static long config_last_size; -static unsigned int config_last_checksum; +static unsigned char config_last_checksum[SHA_DIGEST_LENGTH]; static SETTINGS_REC *settings_get(const char *key, SettingType type) { @@ -661,24 +662,36 @@ void sig_term(int n) raise(SIGTERM); } -/* Yes, this is my own stupid checksum generator, some "real" algorithm - would be nice but would just take more space without much real benefit */ -static unsigned int file_checksum(const char *fname) +static int file_checksum(const char *fname, const unsigned char *old_checksum, + unsigned char *checksum) { - unsigned char buf[512]; - int f, ret, n; - unsigned int checksum = 0; + SHA_CTX c; + unsigned char buf[512], tmp[SHA_DIGEST_LENGTH]; + int f, ret; + + if (!SHA1_Init(&c)) { + return FALSE; + } f = open(fname, O_RDONLY); - if (f == -1) return 0; + if (f == -1) + return FALSE; - n = 0; while ((ret = read(f, buf, sizeof(buf))) > 0) { - while (ret-- > 0) - checksum += buf[ret] << ((n++ & 3)*8); + SHA1_Update(&c, buf, ret); } close(f); - return checksum; + + if (checksum == NULL) { + checksum = tmp; + } + + SHA1_Final(checksum, &c); + + if (old_checksum != NULL) { + return memcmp(checksum, old_checksum, SHA_DIGEST_LENGTH) == 0; + } + return TRUE; } static void irssi_config_save_state(const char *fname) @@ -693,7 +706,7 @@ static void irssi_config_save_state(const char *fname) /* save modify time, file size and checksum */ config_last_mtime = statbuf.st_mtime; config_last_size = statbuf.st_size; - config_last_checksum = file_checksum(fname); + file_checksum(fname, NULL, config_last_checksum); } int irssi_config_is_changed(const char *fname) @@ -707,8 +720,8 @@ int irssi_config_is_changed(const char *fname) return FALSE; return config_last_mtime != statbuf.st_mtime && - (config_last_size != statbuf.st_size || - config_last_checksum != file_checksum(fname)); + (config_last_size != statbuf.st_size || + file_checksum(fname, config_last_checksum, NULL)); } static CONFIG_REC *parse_configfile(const char *fname) From 9c3532f542b839345483f231754dd78b3c06e164 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 12 Feb 2018 22:15:08 +0100 Subject: [PATCH 3/4] implement with glib --- src/core/settings.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 4484deaa..99e7986b 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -29,7 +29,6 @@ #include "settings.h" #include "default-config.h" -#include #include #define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */ @@ -48,7 +47,8 @@ static int timeout_tag; static int config_last_modifycounter; static time_t config_last_mtime; static long config_last_size; -static unsigned char config_last_checksum[SHA_DIGEST_LENGTH]; +static guint8 *config_last_checksum; +static gsize config_last_checksum_length; static SETTINGS_REC *settings_get(const char *key, SettingType type) { @@ -662,14 +662,17 @@ void sig_term(int n) raise(SIGTERM); } -static int file_checksum(const char *fname, const unsigned char *old_checksum, - unsigned char *checksum) +static int file_checksum(const char *fname, const guint8 *old_checksum, gsize old_checksum_length, + guint8 **checksum_out, gsize *checksum_length_out) { - SHA_CTX c; - unsigned char buf[512], tmp[SHA_DIGEST_LENGTH]; + GChecksum *c; + unsigned char buf[512]; + guint8 *checksum; + gsize checksum_length; int f, ret; + static GChecksumType checksum_type = G_CHECKSUM_SHA1; - if (!SHA1_Init(&c)) { + if ((c = g_checksum_new(checksum_type)) == NULL) { return FALSE; } @@ -678,18 +681,23 @@ static int file_checksum(const char *fname, const unsigned char *old_checksum, return FALSE; while ((ret = read(f, buf, sizeof(buf))) > 0) { - SHA1_Update(&c, buf, ret); + g_checksum_update(c, buf, ret); } close(f); - if (checksum == NULL) { - checksum = tmp; + checksum = g_new0(guint8, g_checksum_type_get_length(checksum_type)); + g_checksum_get_digest(c, checksum, &checksum_length); + g_checksum_free(c); + + if (checksum_out != NULL && checksum_length_out != NULL) { + g_free(*checksum_out); + *checksum_out = checksum; + *checksum_length_out = checksum_length; } - SHA1_Final(checksum, &c); - if (old_checksum != NULL) { - return memcmp(checksum, old_checksum, SHA_DIGEST_LENGTH) == 0; + return old_checksum_length == checksum_length && + memcmp(checksum, old_checksum, checksum_length) == 0; } return TRUE; } @@ -706,7 +714,7 @@ static void irssi_config_save_state(const char *fname) /* save modify time, file size and checksum */ config_last_mtime = statbuf.st_mtime; config_last_size = statbuf.st_size; - file_checksum(fname, NULL, config_last_checksum); + file_checksum(fname, NULL, 0, &config_last_checksum, &config_last_checksum_length); } int irssi_config_is_changed(const char *fname) @@ -721,7 +729,7 @@ int irssi_config_is_changed(const char *fname) return config_last_mtime != statbuf.st_mtime && (config_last_size != statbuf.st_size || - file_checksum(fname, config_last_checksum, NULL)); + file_checksum(fname, config_last_checksum, config_last_checksum_length, NULL, NULL)); } static CONFIG_REC *parse_configfile(const char *fname) @@ -919,4 +927,10 @@ void settings_deinit(void) g_hash_table_destroy(settings); if (mainconfig != NULL) config_close(mainconfig); + + if (config_last_checksum != NULL) { + g_free(config_last_checksum); + config_last_checksum = NULL; + config_last_checksum_length = 0; + } } From 2b4e549d449540d72935805b91ead7b18fc1cf39 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 13 Feb 2018 02:01:22 +0100 Subject: [PATCH 4/4] fix usage of checksum_length --- src/core/settings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/settings.c b/src/core/settings.c index 99e7986b..215f38bb 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -685,7 +685,8 @@ static int file_checksum(const char *fname, const guint8 *old_checksum, gsize ol } close(f); - checksum = g_new0(guint8, g_checksum_type_get_length(checksum_type)); + checksum_length = g_checksum_type_get_length(checksum_type); + checksum = g_new0(guint8, checksum_length); g_checksum_get_digest(c, checksum, &checksum_length); g_checksum_free(c);