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,
* 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.
* Represent some numeric value as string of required length.
*
* Units: size units (filesystem sizes are 1K blocks)
* 0=bytes, 1=Kbytes, 2=Mbytes, etc.
* @param len number of characters to represent @size
* @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
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)
{
/* 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. */
/* *INDENT-OFF* */
static const uintmax_t power10[] = {
@ -452,6 +458,7 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
#endif
};
/* *INDENT-ON* */
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 };
@ -493,19 +500,20 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
if (j == units)
{
/* Empty files will print "0" even with minimal width. */
g_snprintf (buffer, len + 1, "%s", "0");
g_snprintf (buffer, sizeof (buffer), "%s", "0");
}
else
{
/* 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;
}
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;
}
@ -515,6 +523,8 @@ size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gbool
else
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. */
const char *size_trunc_sep (uintmax_t size, gboolean use_si);
/* Print file SIZE to BUFFER, but don't exceed LEN characters,
* not including trailing 0. BUFFER should be at least LEN+1 long.
*
/* Return a static string representing size, appending "K" or "M" for
* big sizes. but don't exceed LEN characters,
* 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 *extension (const char *);

View File

@ -407,7 +407,7 @@ chown_cmd (void)
struct stat sf_stat;
const char *fname;
int result;
char buffer[BUF_TINY];
const char *buffer;
uid_t new_user = (uid_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 (1, str_trunc (get_owner (sf_stat.st_uid), 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 (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;
char *s1;
char s2[BUF_SMALL];
const char *s2;
int w, bw1, bw2;
unsigned short i;
@ -524,7 +524,7 @@ overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode)
vfs_path_free (p);
g_free (s1);
/* 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 file modification date & time */
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);
g_free (s1);
/* 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);
/* existing file modification date & time */
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)
{
char buffer[BUF_TINY];
char buffer2[BUF_TINY];
char buffer3[BUF_TINY];
file_op_context_ui_t *ui;
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)
{
struct timeval tv_current;
char buffer4[BUF_TINY];
char buffer2[BUF_TINY], buffer3[BUF_TINY];
gettimeofday (&tv_current, NULL);
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);
else
{
char buffer4[BUF_TINY];
file_bps_prepare_for_show (buffer4, (long) tctx->bps);
g_snprintf (buffer, sizeof (buffer), _("Time: %s %s (%s)"), buffer2, buffer3,
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);
else
{
file_bps_prepare_for_show (buffer4, (long) tctx->bps);
g_snprintf (buffer, sizeof (buffer), _("Time: %s (%s)"), buffer2, buffer4);
file_bps_prepare_for_show (buffer3, (long) tctx->bps);
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)
{
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)
g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2);
else
{
size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si);
g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3);
char *b2;
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);

View File

@ -176,13 +176,16 @@ info_show_info (WInfo * info)
tty_print_string (_("No space information"));
else
{
char buffer1[6], buffer2[6];
char *buffer1;
const char *buffer2;
size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si);
size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si);
buffer1 =
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,
myfs_stats.total == 0 ? 0 :
(int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
g_free (buffer1);
}
MC_FALLTHROUGH;
case 14:
@ -236,8 +239,9 @@ info_show_info (WInfo * info)
else
#endif
{
char buffer[10];
size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si);
const char *buffer;
buffer = size_trunc_len (9, st.st_size, 0, panels_options.kilobyte_si);
tty_printf (_("Size: %s"), buffer);
#ifdef HAVE_STRUCT_STAT_ST_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
if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode))
{
format_device_number (buffer, len + 1, fe->st.st_rdev);
else
return buffer;
}
#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)
{
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,
panels_options.kilobyte_si);
size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1,
panels_options.kilobyte_si);
buffer1 = 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);
g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2,
myfs_stats.total == 0 ? 0 :
(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));
tty_setcolor (NORMAL_COLOR);
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);
else
{
char buffer[BUF_TRUNC_LEN + 1];
const char *buffer;
size_trunc_len (buffer, BUF_TRUNC_LEN, mcview_get_filesize (view), 0,
panels_options.kilobyte_si);
tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end,
buffer, mcview_may_still_grow (view) ? "+" : " ",
buffer =
size_trunc_len (BUF_TRUNC_LEN, mcview_get_filesize (view), 0,
panels_options.kilobyte_si);
tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end, buffer,
mcview_may_still_grow (view) ? "+" : " ",
#ifdef HAVE_CHARSET
mc_global.source_codepage >= 0 ?
get_codepage_id (mc_global.source_codepage) :