From d430cb2972ed8fbad57dc351d81698b4b123d7b4 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Wed, 6 Apr 2016 10:41:42 +0200 Subject: [PATCH] files: allocate enough space for the prompt when finding a lock file Instead of allocating a fixed amount of 128 bytes, which will overflow and segfault, adjust the allocation to the length of the file name, and if necessary trim the file name to make the prompt fit on the screen. This fixes https://savannah.gnu.org/bugs/?47511. Reported-by: Aapo Rantalainen Signed-off-by: Benno Schulenberg --- src/files.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/files.c b/src/files.c index e359ec3..1492d31 100644 --- a/src/files.c +++ b/src/files.c @@ -310,8 +310,8 @@ int delete_lockfile(const char *lockfilename) * complain to the user. */ int do_lockfile(const char *filename) { - char *namecopy1 = (char *) mallocstrcpy(NULL, filename); - char *namecopy2 = (char *) mallocstrcpy(NULL, filename); + char *namecopy = (char *) mallocstrcpy(NULL, filename); + char *secondcopy = (char *) mallocstrcpy(NULL, filename); size_t locknamesize = strlen(filename) + strlen(locking_prefix) + strlen(locking_suffix) + 3; char *lockfilename = charalloc(locknamesize); @@ -319,18 +319,17 @@ int do_lockfile(const char *filename) struct stat fileinfo; int lockfd, lockpid, retval = -1; - snprintf(lockfilename, locknamesize, "%s/%s%s%s", dirname(namecopy1), - locking_prefix, basename(namecopy2), locking_suffix); - free(namecopy1); - free(namecopy2); + snprintf(lockfilename, locknamesize, "%s/%s%s%s", dirname(namecopy), + locking_prefix, basename(secondcopy), locking_suffix); + free(secondcopy); #ifdef DEBUG fprintf(stderr, "lock file name is %s\n", lockfilename); #endif if (stat(lockfilename, &fileinfo) != -1) { ssize_t readtot = 0; ssize_t readamt = 0; - char *lockbuf, *promptstr; - int ans; + char *lockbuf, *question, *promptstr; + int room, ans; if ((lockfd = open(lockfilename, O_RDONLY)) < 0) { statusbar(_("Error opening lock file %s: %s"), @@ -361,10 +360,19 @@ int do_lockfile(const char *filename) fprintf(stderr, "program name which created this lock file should be %s\n", lockprog); fprintf(stderr, "user which created this lock file should be %s\n", lockuser); #endif - promptstr = charalloc(128); /* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */ - sprintf(promptstr, _("File %s is being edited (by %s with %s, PID %d); continue?"), - filename, lockuser, lockprog, lockpid); + question = _("File %s is being edited (by %s with %s, PID %d); continue?"); + room = COLS - strlenpt(question) - strlenpt(lockuser) - strlenpt(lockprog) + 3; + if (room < 4) + namecopy = mallocstrcpy(namecopy, "_"); + else if (room < strlenpt(filename)) + sprintf(namecopy, "...%s", display_string(filename, + strlenpt(filename) - room + 3, room, FALSE)); + + /* Allow extra space for username (14), program name (8), PID (3), + * and terminating \0 (1), minus the %s (2) for the file name. */ + promptstr = charalloc(strlen(question) + 24 + strlen(namecopy)); + sprintf(promptstr, question, namecopy, lockuser, lockprog, lockpid); ans = do_yesno_prompt(FALSE, promptstr); free(promptstr); @@ -377,6 +385,7 @@ int do_lockfile(const char *filename) retval = write_lockfile(lockfilename, filename, FALSE); free_the_name: + free(namecopy); if (retval < 1) free(lockfilename); -- 2.8.1