fix stack smashing, buffer overflow and invalid output of pr (#772172)

This commit is contained in:
Kamil Dudka 2012-01-16 15:38:16 +01:00
parent 33b6b75afa
commit ad3d42ec4f
2 changed files with 61 additions and 38 deletions

View File

@ -1786,7 +1786,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
int *number); int *number);
static void print_files (int number_of_files, char **av); static void print_files (int number_of_files, char **av);
static void init_parameters (int number_of_files); static void init_parameters (int number_of_files);
@@ -439,7 +491,6 @@ static void store_char (char c); @@ -438,7 +490,6 @@ static void store_char (char c);
static void pad_down (int lines); static void pad_down (int lines);
static void read_rest_of_line (COLUMN *p); static void read_rest_of_line (COLUMN *p);
static void skip_read (COLUMN *p, int column_number); static void skip_read (COLUMN *p, int column_number);
@ -1794,7 +1794,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
static void cleanup (void); static void cleanup (void);
static void print_sep_string (void); static void print_sep_string (void);
static void separator_string (const char *optarg_S); static void separator_string (const char *optarg_S);
@@ -451,7 +502,7 @@ static COLUMN *column_vector; @@ -450,7 +501,7 @@ static COLUMN *column_vector;
we store the leftmost columns contiguously in buff. we store the leftmost columns contiguously in buff.
To print a line from buff, get the index of the first character To print a line from buff, get the index of the first character
from line_vector[i], and print up to line_vector[i + 1]. */ from line_vector[i], and print up to line_vector[i + 1]. */
@ -1803,7 +1803,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* Index of the position in buff where the next character /* Index of the position in buff where the next character
will be stored. */ will be stored. */
@@ -555,7 +606,7 @@ static int chars_per_column; @@ -554,7 +605,7 @@ static int chars_per_column;
static bool untabify_input = false; static bool untabify_input = false;
/* (-e) The input tab character. */ /* (-e) The input tab character. */
@ -1812,7 +1812,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
where the leftmost column is 1. */ where the leftmost column is 1. */
@@ -565,7 +616,10 @@ static int chars_per_input_tab = 8; @@ -564,7 +615,10 @@ static int chars_per_input_tab = 8;
static bool tabify_output = false; static bool tabify_output = false;
/* (-i) The output tab character. */ /* (-i) The output tab character. */
@ -1824,7 +1824,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* (-i) The width of the output tab. */ /* (-i) The width of the output tab. */
static int chars_per_output_tab = 8; static int chars_per_output_tab = 8;
@@ -639,7 +693,13 @@ static int power_10; @@ -638,7 +692,13 @@ static int power_10;
static bool numbered_lines = false; static bool numbered_lines = false;
/* (-n) Character which follows each line number. */ /* (-n) Character which follows each line number. */
@ -1839,7 +1839,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* (-n) line counting starts with 1st line of input file (not with 1st /* (-n) line counting starts with 1st line of input file (not with 1st
line of 1st page printed). */ line of 1st page printed). */
@@ -692,6 +752,7 @@ static bool use_col_separator = false; @@ -691,6 +751,7 @@ static bool use_col_separator = false;
-a|COLUMN|-m is a `space' and with the -J option a `tab'. */ -a|COLUMN|-m is a `space' and with the -J option a `tab'. */
static char *col_sep_string = (char *) ""; static char *col_sep_string = (char *) "";
static int col_sep_length = 0; static int col_sep_length = 0;
@ -1847,7 +1847,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
static char *column_separator = (char *) " "; static char *column_separator = (char *) " ";
static char *line_separator = (char *) "\t"; static char *line_separator = (char *) "\t";
@@ -848,6 +909,13 @@ separator_string (const char *optarg_S) @@ -847,6 +908,13 @@ separator_string (const char *optarg_S)
col_sep_length = (int) strlen (optarg_S); col_sep_length = (int) strlen (optarg_S);
col_sep_string = xmalloc (col_sep_length + 1); col_sep_string = xmalloc (col_sep_length + 1);
strcpy (col_sep_string, optarg_S); strcpy (col_sep_string, optarg_S);
@ -1861,7 +1861,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
} }
int int
@@ -872,6 +940,21 @@ main (int argc, char **argv) @@ -871,6 +939,21 @@ main (int argc, char **argv)
atexit (close_stdout); atexit (close_stdout);
@ -1883,7 +1883,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
n_files = 0; n_files = 0;
file_names = (argc > 1 file_names = (argc > 1
? xmalloc ((argc - 1) * sizeof (char *)) ? xmalloc ((argc - 1) * sizeof (char *))
@@ -948,8 +1031,12 @@ main (int argc, char **argv) @@ -947,8 +1030,12 @@ main (int argc, char **argv)
break; break;
case 'e': case 'e':
if (optarg) if (optarg)
@ -1898,7 +1898,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* Could check tab width > 0. */ /* Could check tab width > 0. */
untabify_input = true; untabify_input = true;
break; break;
@@ -962,8 +1049,12 @@ main (int argc, char **argv) @@ -961,8 +1048,12 @@ main (int argc, char **argv)
break; break;
case 'i': case 'i':
if (optarg) if (optarg)
@ -1913,7 +1913,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* Could check tab width > 0. */ /* Could check tab width > 0. */
tabify_output = true; tabify_output = true;
break; break;
@@ -990,8 +1081,8 @@ main (int argc, char **argv) @@ -989,8 +1080,8 @@ main (int argc, char **argv)
case 'n': case 'n':
numbered_lines = true; numbered_lines = true;
if (optarg) if (optarg)
@ -1924,7 +1924,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
break; break;
case 'N': case 'N':
skip_count = false; skip_count = false;
@@ -1030,7 +1121,7 @@ main (int argc, char **argv) @@ -1029,7 +1120,7 @@ main (int argc, char **argv)
old_s = false; old_s = false;
/* Reset an additional input of -s, -S dominates -s */ /* Reset an additional input of -s, -S dominates -s */
col_sep_string = bad_cast (""); col_sep_string = bad_cast ("");
@ -1933,7 +1933,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
use_col_separator = true; use_col_separator = true;
if (optarg) if (optarg)
separator_string (optarg); separator_string (optarg);
@@ -1187,10 +1278,45 @@ main (int argc, char **argv) @@ -1186,10 +1277,45 @@ main (int argc, char **argv)
a number. */ a number. */
static void static void
@ -1981,7 +1981,19 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
if (*arg) if (*arg)
{ {
long int tmp_long; long int tmp_long;
@@ -1249,7 +1375,7 @@ init_parameters (int number_of_files) @@ -1211,6 +1337,11 @@ static void
init_parameters (int number_of_files)
{
int chars_used_by_number = 0;
+ int mb_len = 1;
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1)
+ mb_len = MB_LEN_MAX;
+#endif
lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
if (lines_per_body <= 0)
@@ -1248,7 +1379,7 @@ init_parameters (int number_of_files)
else else
col_sep_string = column_separator; col_sep_string = column_separator;
@ -1990,7 +2002,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
use_col_separator = true; use_col_separator = true;
} }
/* It's rather pointless to define a TAB separator with column /* It's rather pointless to define a TAB separator with column
@@ -1280,11 +1406,11 @@ init_parameters (int number_of_files) @@ -1279,11 +1410,11 @@ init_parameters (int number_of_files)
TAB_WIDTH (chars_per_input_tab, chars_per_number); */ TAB_WIDTH (chars_per_input_tab, chars_per_number); */
/* Estimate chars_per_text without any margin and keep it constant. */ /* Estimate chars_per_text without any margin and keep it constant. */
@ -2004,7 +2016,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* The number is part of the column width unless we are /* The number is part of the column width unless we are
printing files in parallel. */ printing files in parallel. */
@@ -1299,7 +1425,7 @@ init_parameters (int number_of_files) @@ -1298,7 +1429,7 @@ init_parameters (int number_of_files)
} }
chars_per_column = (chars_per_line - chars_used_by_number - chars_per_column = (chars_per_line - chars_used_by_number -
@ -2013,7 +2025,16 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
if (chars_per_column < 1) if (chars_per_column < 1)
error (EXIT_FAILURE, 0, _("page width too narrow")); error (EXIT_FAILURE, 0, _("page width too narrow"));
@@ -1424,7 +1550,7 @@ init_funcs (void) @@ -1315,7 +1446,7 @@ init_parameters (int number_of_files)
We've to use 8 as the lower limit, if we use chars_per_default_tab = 8
to expand a tab which is not an input_tab-char. */
free (clump_buff);
- clump_buff = xmalloc (MAX (8, chars_per_input_tab));
+ clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab));
}
/* Open the necessary files,
@@ -1423,7 +1554,7 @@ init_funcs (void)
/* Enlarge p->start_position of first column to use the same form of /* Enlarge p->start_position of first column to use the same form of
padding_not_printed with all columns. */ padding_not_printed with all columns. */
@ -2022,7 +2043,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* This loop takes care of all but the rightmost column. */ /* This loop takes care of all but the rightmost column. */
@@ -1458,7 +1584,7 @@ init_funcs (void) @@ -1457,7 +1588,7 @@ init_funcs (void)
} }
else else
{ {
@ -2031,7 +2052,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
h_next = h + chars_per_column; h_next = h + chars_per_column;
} }
} }
@@ -1749,9 +1875,9 @@ static void @@ -1748,9 +1879,9 @@ static void
align_column (COLUMN *p) align_column (COLUMN *p)
{ {
padding_not_printed = p->start_position; padding_not_printed = p->start_position;
@ -2043,7 +2064,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
padding_not_printed = ANYWHERE; padding_not_printed = ANYWHERE;
} }
@@ -2022,13 +2148,13 @@ store_char (char c) @@ -2021,13 +2152,13 @@ store_char (char c)
/* May be too generous. */ /* May be too generous. */
buff = X2REALLOC (buff, &buff_allocated); buff = X2REALLOC (buff, &buff_allocated);
} }
@ -2059,7 +2080,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
char *s; char *s;
int left_cut; int left_cut;
@@ -2051,22 +2177,24 @@ add_line_number (COLUMN *p) @@ -2050,22 +2181,24 @@ add_line_number (COLUMN *p)
/* Tabification is assumed for multiple columns, also for n-separators, /* Tabification is assumed for multiple columns, also for n-separators,
but `default n-separator = TAB' hasn't been given priority over but `default n-separator = TAB' hasn't been given priority over
equal column_width also specified by POSIX. */ equal column_width also specified by POSIX. */
@ -2088,7 +2109,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
output_position = POS_AFTER_TAB (chars_per_output_tab, output_position = POS_AFTER_TAB (chars_per_output_tab,
output_position); output_position);
} }
@@ -2227,7 +2355,7 @@ print_white_space (void) @@ -2226,7 +2359,7 @@ print_white_space (void)
while (goal - h_old > 1 while (goal - h_old > 1
&& (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
{ {
@ -2097,7 +2118,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
h_old = h_new; h_old = h_new;
} }
while (++h_old <= goal) while (++h_old <= goal)
@@ -2247,6 +2375,7 @@ print_sep_string (void) @@ -2246,6 +2379,7 @@ print_sep_string (void)
{ {
char *s; char *s;
int l = col_sep_length; int l = col_sep_length;
@ -2105,7 +2126,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
s = col_sep_string; s = col_sep_string;
@@ -2260,6 +2389,7 @@ print_sep_string (void) @@ -2259,6 +2393,7 @@ print_sep_string (void)
{ {
for (; separators_not_printed > 0; --separators_not_printed) for (; separators_not_printed > 0; --separators_not_printed)
{ {
@ -2113,7 +2134,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
while (l-- > 0) while (l-- > 0)
{ {
/* 3 types of sep_strings: spaces only, spaces and chars, /* 3 types of sep_strings: spaces only, spaces and chars,
@@ -2273,12 +2403,15 @@ print_sep_string (void) @@ -2272,12 +2407,15 @@ print_sep_string (void)
} }
else else
{ {
@ -2130,7 +2151,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* sep_string ends with some spaces */ /* sep_string ends with some spaces */
if (spaces_not_printed > 0) if (spaces_not_printed > 0)
print_white_space (); print_white_space ();
@@ -2306,7 +2439,7 @@ print_clump (COLUMN *p, int n, char *clu @@ -2305,7 +2443,7 @@ print_clump (COLUMN *p, int n, char *clump)
required number of tabs and spaces. */ required number of tabs and spaces. */
static void static void
@ -2139,7 +2160,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
{ {
if (tabify_output) if (tabify_output)
{ {
@@ -2330,6 +2463,74 @@ print_char (char c) @@ -2329,6 +2467,74 @@ print_char (char c)
putchar (c); putchar (c);
} }
@ -2214,7 +2235,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
/* Skip to page PAGE before printing. /* Skip to page PAGE before printing.
PAGE may be larger than total number of pages. */ PAGE may be larger than total number of pages. */
@@ -2509,9 +2710,9 @@ read_line (COLUMN *p) @@ -2508,9 +2714,9 @@ read_line (COLUMN *p)
align_empty_cols = false; align_empty_cols = false;
} }
@ -2226,7 +2247,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
padding_not_printed = ANYWHERE; padding_not_printed = ANYWHERE;
} }
@@ -2612,9 +2813,9 @@ print_stored (COLUMN *p) @@ -2611,9 +2817,9 @@ print_stored (COLUMN *p)
} }
} }
@ -2238,7 +2259,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
padding_not_printed = ANYWHERE; padding_not_printed = ANYWHERE;
} }
@@ -2627,8 +2828,8 @@ print_stored (COLUMN *p) @@ -2626,8 +2832,8 @@ print_stored (COLUMN *p)
if (spaces_not_printed == 0) if (spaces_not_printed == 0)
{ {
output_position = p->start_position + end_vector[line]; output_position = p->start_position + end_vector[line];
@ -2249,7 +2270,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
} }
return true; return true;
@@ -2647,7 +2848,7 @@ print_stored (COLUMN *p) @@ -2646,7 +2852,7 @@ print_stored (COLUMN *p)
number of characters is 1.) */ number of characters is 1.) */
static int static int
@ -2258,7 +2279,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
{ {
unsigned char uc = c; unsigned char uc = c;
char *s = clump_buff; char *s = clump_buff;
@@ -2657,10 +2858,10 @@ char_to_clump (char c) @@ -2656,10 +2862,10 @@ char_to_clump (char c)
int chars; int chars;
int chars_per_c = 8; int chars_per_c = 8;
@ -2271,7 +2292,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
{ {
width = TAB_WIDTH (chars_per_c, input_position); width = TAB_WIDTH (chars_per_c, input_position);
@@ -2741,6 +2942,155 @@ char_to_clump (char c) @@ -2740,6 +2946,154 @@ char_to_clump (char c)
return chars; return chars;
} }
@ -2279,7 +2300,6 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
+static int +static int
+char_to_clump_multi (char c) +char_to_clump_multi (char c)
+{ +{
+ unsigned char uc = c;
+ static size_t mbc_pos = 0; + static size_t mbc_pos = 0;
+ static char mbc[MB_LEN_MAX] = {'\0'}; + static char mbc[MB_LEN_MAX] = {'\0'};
+ static mbstate_t state = {'\0'}; + static mbstate_t state = {'\0'};
@ -2317,7 +2337,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
+ width = +4; + width = +4;
+ chars = +4; + chars = +4;
+ *s++ = '\\'; + *s++ = '\\';
+ sprintf (esc_buff, "%03o", mbc[0]); + sprintf (esc_buff, "%03o", (unsigned char) mbc[0]);
+ for (i = 0; i <= 2; ++i) + for (i = 0; i <= 2; ++i)
+ *s++ = (int) esc_buff[i]; + *s++ = (int) esc_buff[i];
+ } + }
@ -2366,7 +2386,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
+ width += 4; + width += 4;
+ chars += 4; + chars += 4;
+ *s++ = '\\'; + *s++ = '\\';
+ sprintf (esc_buff, "%03o", uc); + sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
+ for (j = 0; j <= 2; ++j) + for (j = 0; j <= 2; ++j)
+ *s++ = (int) esc_buff[j]; + *s++ = (int) esc_buff[j];
+ } + }
@ -2387,7 +2407,7 @@ diff -urNp coreutils-8.13-orig/src/pr.c coreutils-8.13/src/pr.c
+ width += 4; + width += 4;
+ chars += 4; + chars += 4;
+ *s++ = '\\'; + *s++ = '\\';
+ sprintf (esc_buff, "%03o", uc); + sprintf (esc_buff, "%03o", (unsigned char) mbc[i]);
+ for (j = 0; j <= 2; ++j) + for (j = 0; j <= 2; ++j)
+ *s++ = (int) esc_buff[j]; + *s++ = (int) esc_buff[j];
+ } + }

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils Name: coreutils
Version: 8.15 Version: 8.15
Release: 1%{?dist} Release: 2%{?dist}
License: GPLv3+ License: GPLv3+
Group: System Environment/Base Group: System Environment/Base
Url: http://www.gnu.org/software/coreutils/ Url: http://www.gnu.org/software/coreutils/
@ -322,6 +322,9 @@ fi
%{?!norunuser:/sbin/runuser} %{?!norunuser:/sbin/runuser}
%changelog %changelog
* Mon Jan 16 2012 Kamil Dudka <kdudka@redhat.com> - 8.15-2
- fix stack smashing, buffer overflow, and invalid output of pr (#772172)
* Sat Jan 07 2012 Ondrej Vasik <ovasik@redhat.com> - 8.15-1 * Sat Jan 07 2012 Ondrej Vasik <ovasik@redhat.com> - 8.15-1
- new upstream release 8.15 - new upstream release 8.15