From 1ac300932deab8dea2c43050921bbbdb36d62ff1 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 16 Nov 2009 15:52:45 +0100 Subject: more: limited line buffer length results in corrupted UTF-8 text Addresses-Debian-Bug: #552608 Reported-By: Roger Leigh Signed-off-by: Karel Zak --- text-utils/more.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'text-utils/more.c') diff --git a/text-utils/more.c b/text-utils/more.c index 45a58e271..a152463c0 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -105,9 +105,10 @@ int get_line(register FILE *f, int *length); void prbuf (register char *s, register int n); void execute (char *filename, char *cmd, ...); FILE *checkf (char *, int *); +int prepare_line_buffer(void); #define TBUFSIZ 1024 -#define LINSIZ 256 +#define LINSIZ 256 /* minimal Line buffer size */ #define ctrl(letter) (letter & 077) #define RUBOUT '\177' #define ESC '\033' @@ -141,7 +142,8 @@ int nfiles; /* Number of files left to process */ char *shell; /* The name of the shell to use */ int shellp; /* A previous shell command exists */ sigjmp_buf restore; -char Line[LINSIZ+2]; /* Line buffer */ +char *Line; /* Line buffer */ +size_t LineLen; /* size of Line buffer */ int Lpp = 24; /* lines per page */ char *Clear; /* clear screen */ char *eraseln; /* erase line */ @@ -284,6 +286,10 @@ int main(int argc, char **argv) { fnames = argv; setlocale(LC_ALL, ""); initterm (); + if (prepare_line_buffer()) { + fprintf(stderr, _("failed to initialize line buffer\n")); + exit(1); + } nscroll = Lpp/2 - 1; if (nscroll <= 0) nscroll = 1; @@ -767,6 +773,32 @@ static void prompt (char *filename) inwait++; } +int prepare_line_buffer(void) +{ + char *nline; + size_t nsz = Mcol * 4; + + if (LineLen >= nsz) + return 0; + + if (nsz < LINSIZ) + nsz = LINSIZ; + + nline = realloc(Line, nsz); + if (nline) { + Line = nline; + LineLen = nsz; + return 0; + } + + /* error() uses siglongjmp(), we want to return from this + * function when the Line buffer is initilized first time in main() + */ + if (Line) + error(_("out if memory")); + return -1; +} + /* * Get a logical line */ @@ -793,6 +825,8 @@ int get_line(register FILE *f, int *length) memset (&state, '\0', sizeof (mbstate_t)); #endif + prepare_line_buffer(); + p = Line; column = 0; c = Getc (f); @@ -800,7 +834,7 @@ int get_line(register FILE *f, int *length) Currline++; c = Getc (f); } - while (p < &Line[LINSIZ - 1]) { + while (p < &Line[LineLen - 1]) { #ifdef HAVE_WIDECHAR if (fold_opt && use_mbc_buffer_flag && MB_CUR_MAX > 1) { use_mbc_buffer_flag = 0; @@ -871,11 +905,11 @@ process_mbc: #if 0 if (c == '\033') { /* ESC */ c = Getc(f); - while (c > ' ' && c < '0' && p < &Line[LINSIZ - 1]) { + while (c > ' ' && c < '0' && p < &Line[LineLen - 1]) { *p++ = c; c = Getc(f); } - if (c >= '0' && c < '\177' && p < &Line[LINSIZ - 1]) { + if (c >= '0' && c < '\177' && p < &Line[LineLen - 1]) { *p++ = c; c = Getc(f); continue; @@ -890,7 +924,7 @@ process_mbc: promptlen = 0; } else { - for (--p; p < &Line[LINSIZ - 1];) { + for (--p; p < &Line[LineLen - 1];) { *p++ = ' '; if ((++column & 7) == 0) break; @@ -2087,8 +2121,10 @@ void rdline (register FILE *f) register int c; register char *p; + prepare_line_buffer(); + p = Line; - while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) + while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LineLen - 1) *p++ = c; if (c == '\n') Currline++; -- cgit v1.2.3-55-g7522