Ticket #3666: Improper use of IEC and SI prefixes for size in size_trunc().

(size_trunc_len): return statically allocated buffer.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2016-11-08 10:59:55 +03:00
parent 37fcb210f2
commit fdd9ab4098
7 changed files with 69 additions and 46 deletions

View File

@ -405,18 +405,24 @@ size_trunc_sep (uintmax_t size, gboolean use_si)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/** /**
* Print file SIZE to BUFFER, but don't exceed LEN characters, * Represent some numeric value as string of required length.
* not including trailing 0. BUFFER should be at least LEN+1 long.
* This function is called for every file on panels, so avoid
* floating point by any means.
* *
* Units: size units (filesystem sizes are 1K blocks) * @param len number of characters to represent @size
* 0=bytes, 1=Kbytes, 2=Mbytes, etc. * @param size value to represent
* @param units @size units: 0=bytes, 1=Kbytes, 2=Mbytes, etc.
* @param use_si use SI or IEC units (10- or 2-based respectively)
*
* @return static buffer
*/ */
void const char *
size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si) size_trunc_len (unsigned int len, uintmax_t size, int units, gboolean use_si)
{ {
/* This function is called for every file on panels, so avoid floating point by any means. */
/* Enough space to represent uintmax_t value with units */
static char buffer[BUF_TINY];
/* Avoid taking power for every file. */ /* Avoid taking power for every file. */
/* *INDENT-OFF* */ /* *INDENT-OFF* */
static const uintmax_t power10[] = { static const uintmax_t power10[] = {
@ -452,6 +458,7 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
#endif #endif
}; };
/* *INDENT-ON* */ /* *INDENT-ON* */
static const char *const suffix[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", NULL }; static const char *const suffix[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", NULL };
static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL }; static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL };
@ -493,19 +500,20 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
if (j == units) if (j == units)
{ {
/* Empty files will print "0" even with minimal width. */ /* Empty files will print "0" even with minimal width. */
g_snprintf (buffer, len + 1, "%s", "0"); g_snprintf (buffer, sizeof (buffer), "%s", "0");
} }
else else
{ {
/* Use "~K" or just "K" if len is 1. Use "B" for bytes. */ /* Use "~K" or just "K" if len is 1. Use "B" for bytes. */
g_snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s", (j > 1) ? sfx[j - 1] : "B"); g_snprintf (buffer, sizeof (buffer), (len > 1) ? "~%s" : "%s",
(j > 1) ? sfx[j - 1] : "B");
} }
break; break;
} }
if (size < power10[len - (j > 0 ? 1 : 0)]) if (size < power10[len - (j > 0 ? 1 : 0)])
{ {
g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]); g_snprintf (buffer, sizeof (buffer), "%" PRIuMAX "%s", size, sfx[j]);
break; break;
} }
@ -515,6 +523,8 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
else else
size = (size + 512) >> 10; size = (size + 512) >> 10;
} }
return buffer;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */

View File

@ -150,11 +150,11 @@ const char *size_trunc (uintmax_t size, gboolean use_si);
* NOTE: uses the same static buffer as size_trunc. */ * NOTE: uses the same static buffer as size_trunc. */
const char *size_trunc_sep (uintmax_t size, gboolean use_si); const char *size_trunc_sep (uintmax_t size, gboolean use_si);
/* Print file SIZE to BUFFER, but don't exceed LEN characters, /* Return a static string representing size, appending "K" or "M" for
* not including trailing 0. BUFFER should be at least LEN+1 long. * big sizes. but don't exceed LEN characters,
*
* Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */ * Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */
void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si); const char *size_trunc_len (unsigned int len, uintmax_t size, int units, gboolean use_si);
const char *string_perm (mode_t mode_bits); const char *string_perm (mode_t mode_bits);
const char *extension (const char *); const char *extension (const char *);

View File

@ -407,7 +407,7 @@ chown_cmd (void)
struct stat sf_stat; struct stat sf_stat;
const char *fname; const char *fname;
int result; int result;
char buffer[BUF_TINY]; const char *buffer;
uid_t new_user = (uid_t) (-1); uid_t new_user = (uid_t) (-1);
gid_t new_group = (gid_t) (-1); gid_t new_group = (gid_t) (-1);
@ -438,7 +438,7 @@ chown_cmd (void)
chown_label (0, str_trunc (fname, GW - 4)); chown_label (0, str_trunc (fname, GW - 4));
chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4)); chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4));
chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4)); chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4));
size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si); buffer = size_trunc_len (GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si);
chown_label (3, buffer); chown_label (3, buffer);
chown_label (4, string_perm (sf_stat.st_mode)); chown_label (4, string_perm (sf_stat.st_mode));

View File

@ -491,7 +491,7 @@ overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode)
vfs_path_t *p; vfs_path_t *p;
char *s1; char *s1;
char s2[BUF_SMALL]; const char *s2;
int w, bw1, bw2; int w, bw1, bw2;
unsigned short i; unsigned short i;
@ -524,7 +524,7 @@ overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode)
vfs_path_free (p); vfs_path_free (p);
g_free (s1); g_free (s1);
/* new file size */ /* new file size */
size_trunc_len (s2, sizeof (s2), ui->src_stat->st_size, 0, panels_options.kilobyte_si); s2 = size_trunc_len (BUF_SMALL - 1, ui->src_stat->st_size, 0, panels_options.kilobyte_si);
NEW_LABEL (2, s2); NEW_LABEL (2, s2);
/* new file modification date & time */ /* new file modification date & time */
s1 = (char *) file_date (ui->src_stat->st_mtime); s1 = (char *) file_date (ui->src_stat->st_mtime);
@ -539,7 +539,7 @@ overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode)
vfs_path_free (p); vfs_path_free (p);
g_free (s1); g_free (s1);
/* existing file size */ /* existing file size */
size_trunc_len (s2, sizeof (s2), ui->dst_stat->st_size, 0, panels_options.kilobyte_si); s2 = size_trunc_len (BUF_SMALL - 1, ui->dst_stat->st_size, 0, panels_options.kilobyte_si);
NEW_LABEL (6, s2); NEW_LABEL (6, s2);
/* existing file modification date & time */ /* existing file modification date & time */
s1 = (char *) file_date (ui->dst_stat->st_mtime); s1 = (char *) file_date (ui->dst_stat->st_mtime);
@ -1030,8 +1030,6 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
uintmax_t copied_bytes, gboolean show_summary) uintmax_t copied_bytes, gboolean show_summary)
{ {
char buffer[BUF_TINY]; char buffer[BUF_TINY];
char buffer2[BUF_TINY];
char buffer3[BUF_TINY];
file_op_context_ui_t *ui; file_op_context_ui_t *ui;
if (ctx == NULL || ctx->ui == NULL) if (ctx == NULL || ctx->ui == NULL)
@ -1057,7 +1055,7 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
if (ui->time_label != NULL) if (ui->time_label != NULL)
{ {
struct timeval tv_current; struct timeval tv_current;
char buffer4[BUF_TINY]; char buffer2[BUF_TINY], buffer3[BUF_TINY];
gettimeofday (&tv_current, NULL); gettimeofday (&tv_current, NULL);
file_frmt_time (buffer2, tv_current.tv_sec - tctx->transfer_start.tv_sec); file_frmt_time (buffer2, tv_current.tv_sec - tctx->transfer_start.tv_sec);
@ -1069,6 +1067,8 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
g_snprintf (buffer, sizeof (buffer), _("Time: %s %s"), buffer2, buffer3); g_snprintf (buffer, sizeof (buffer), _("Time: %s %s"), buffer2, buffer3);
else else
{ {
char buffer4[BUF_TINY];
file_bps_prepare_for_show (buffer4, (long) tctx->bps); file_bps_prepare_for_show (buffer4, (long) tctx->bps);
g_snprintf (buffer, sizeof (buffer), _("Time: %s %s (%s)"), buffer2, buffer3, g_snprintf (buffer, sizeof (buffer), _("Time: %s %s (%s)"), buffer2, buffer3,
buffer4); buffer4);
@ -1080,8 +1080,8 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
g_snprintf (buffer, sizeof (buffer), _("Time: %s"), buffer2); g_snprintf (buffer, sizeof (buffer), _("Time: %s"), buffer2);
else else
{ {
file_bps_prepare_for_show (buffer4, (long) tctx->bps); file_bps_prepare_for_show (buffer3, (long) tctx->bps);
g_snprintf (buffer, sizeof (buffer), _("Time: %s (%s)"), buffer2, buffer4); g_snprintf (buffer, sizeof (buffer), _("Time: %s (%s)"), buffer2, buffer3);
} }
} }
@ -1090,14 +1090,19 @@ file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct
if (ui->total_bytes_label != NULL) if (ui->total_bytes_label != NULL)
{ {
size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si); const char *buffer2, *buffer3;
buffer2 = size_trunc_len (5, tctx->copied_bytes, 0, panels_options.kilobyte_si);
if (!ctx->progress_totals_computed) if (!ctx->progress_totals_computed)
g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2); g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2);
else else
{ {
size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si); char *b2;
g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3);
b2 = g_strdup (buffer2);
buffer3 = size_trunc_len (5, ctx->progress_bytes, 0, panels_options.kilobyte_si);
g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), b2, buffer3);
g_free (b2);
} }
hline_set_text (ui->total_bytes_label, buffer); hline_set_text (ui->total_bytes_label, buffer);

View File

@ -176,13 +176,16 @@ info_show_info (WInfo * info)
tty_print_string (_("No space information")); tty_print_string (_("No space information"));
else else
{ {
char buffer1[6], buffer2[6]; char *buffer1;
const char *buffer2;
size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si); buffer1 =
size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si); g_strdup (size_trunc_len (5, myfs_stats.avail, 1, panels_options.kilobyte_si));
buffer2 = size_trunc_len (5, myfs_stats.total, 1, panels_options.kilobyte_si);
tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2, tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2,
myfs_stats.total == 0 ? 0 : myfs_stats.total == 0 ? 0 :
(int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
g_free (buffer1);
} }
MC_FALLTHROUGH; MC_FALLTHROUGH;
case 14: case 14:
@ -236,8 +239,9 @@ info_show_info (WInfo * info)
else else
#endif #endif
{ {
char buffer[10]; const char *buffer;
size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si);
buffer = size_trunc_len (9, st.st_size, 0, panels_options.kilobyte_si);
tty_printf (_("Size: %s"), buffer); tty_printf (_("Size: %s"), buffer);
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
tty_printf (ngettext (" (%lu block)", " (%lu blocks)", tty_printf (ngettext (" (%lu block)", " (%lu blocks)",

View File

@ -512,12 +512,13 @@ string_file_size (file_entry_t * fe, int len)
#ifdef HAVE_STRUCT_STAT_ST_RDEV #ifdef HAVE_STRUCT_STAT_ST_RDEV
if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode)) if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode))
{
format_device_number (buffer, len + 1, fe->st.st_rdev); format_device_number (buffer, len + 1, fe->st.st_rdev);
else return buffer;
}
#endif #endif
size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si);
return buffer; return size_trunc_len ((unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -1154,15 +1155,17 @@ show_free_space (const WPanel * panel)
if (myfs_stats.avail != 0 || myfs_stats.total != 0) if (myfs_stats.avail != 0 || myfs_stats.total != 0)
{ {
const Widget *w = CONST_WIDGET (panel); const Widget *w = CONST_WIDGET (panel);
char buffer1[6], buffer2[6], tmp[BUF_SMALL]; char *buffer1;
const char *buffer2;
char tmp[BUF_SMALL];
size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1, buffer1 = g_strdup (size_trunc_len (5, myfs_stats.avail, 1, panels_options.kilobyte_si));
panels_options.kilobyte_si); buffer2 = size_trunc_len (5, myfs_stats.total, 1, panels_options.kilobyte_si);
size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1,
panels_options.kilobyte_si);
g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2, g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2,
myfs_stats.total == 0 ? 0 : myfs_stats.total == 0 ? 0 :
(int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
g_free (buffer1);
/* FIX LEGACY: use str_term_width1() instead of strlen() here */
widget_move (w, w->lines - 1, w->cols - 2 - (int) strlen (tmp)); widget_move (w, w->lines - 1, w->cols - 2 - (int) strlen (tmp));
tty_setcolor (NORMAL_COLOR); tty_setcolor (NORMAL_COLOR);
tty_print_string (tmp); tty_print_string (tmp);

View File

@ -169,12 +169,13 @@ mcview_display_status (WView * view)
tty_printf ("0x%08" PRIxMAX, (uintmax_t) view->hex_cursor); tty_printf ("0x%08" PRIxMAX, (uintmax_t) view->hex_cursor);
else else
{ {
char buffer[BUF_TRUNC_LEN + 1]; const char *buffer;
size_trunc_len (buffer, BUF_TRUNC_LEN, mcview_get_filesize (view), 0, buffer =
panels_options.kilobyte_si); size_trunc_len (BUF_TRUNC_LEN, mcview_get_filesize (view), 0,
tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end, panels_options.kilobyte_si);
buffer, mcview_may_still_grow (view) ? "+" : " ", tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end, buffer,
mcview_may_still_grow (view) ? "+" : " ",
#ifdef HAVE_CHARSET #ifdef HAVE_CHARSET
mc_global.source_codepage >= 0 ? mc_global.source_codepage >= 0 ?
get_codepage_id (mc_global.source_codepage) : get_codepage_id (mc_global.source_codepage) :