From 6d5a41b38b55258213ecfaae9df7a758caa752a1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 15 Feb 2017 01:46:47 +0000 Subject: [PATCH] upstream commit fix division by zero crash in "df" output when server returns zero total filesystem blocks/inodes. Spotted by Guido Vranken; ok dtucker@ Upstream-ID: 6fb6c2ae6b289aa07b6232dbc0be54682ef5419f --- sftp.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sftp.c b/sftp.c index 2b8fdabfb..76add3908 100644 --- a/sftp.c +++ b/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.177 2016/10/18 12:41:22 millert Exp $ */ +/* $OpenBSD: sftp.c,v 1.178 2017/02/15 01:46:47 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -969,23 +969,34 @@ static int do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) { struct sftp_statvfs st; - char s_used[FMT_SCALED_STRSIZE]; - char s_avail[FMT_SCALED_STRSIZE]; - char s_root[FMT_SCALED_STRSIZE]; - char s_total[FMT_SCALED_STRSIZE]; - unsigned long long ffree; + char s_used[FMT_SCALED_STRSIZE], s_avail[FMT_SCALED_STRSIZE]; + char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE]; + char s_icapacity[16], s_dcapacity[16]; if (do_statvfs(conn, path, &st, 1) == -1) return -1; + if (st.f_files == 0) + strlcpy(s_icapacity, "ERR", sizeof(s_icapacity)); + else { + snprintf(s_icapacity, sizeof(s_icapacity), "%3llu%%", + (unsigned long long)(100 * (st.f_files - st.f_ffree) / + st.f_files)); + } + if (st.f_blocks == 0) + strlcpy(s_dcapacity, "ERR", sizeof(s_dcapacity)); + else { + snprintf(s_dcapacity, sizeof(s_dcapacity), "%3llu%%", + (unsigned long long)(100 * (st.f_blocks - st.f_bfree) / + st.f_blocks)); + } if (iflag) { - ffree = st.f_files ? (100 * (st.f_files - st.f_ffree) / st.f_files) : 0; printf(" Inodes Used Avail " "(root) %%Capacity\n"); - printf("%11llu %11llu %11llu %11llu %3llu%%\n", + printf("%11llu %11llu %11llu %11llu %s\n", (unsigned long long)st.f_files, (unsigned long long)(st.f_files - st.f_ffree), (unsigned long long)st.f_favail, - (unsigned long long)st.f_ffree, ffree); + (unsigned long long)st.f_ffree, s_icapacity); } else if (hflag) { strlcpy(s_used, "error", sizeof(s_used)); strlcpy(s_avail, "error", sizeof(s_avail)); @@ -996,21 +1007,18 @@ do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) fmt_scaled(st.f_bfree * st.f_frsize, s_root); fmt_scaled(st.f_blocks * st.f_frsize, s_total); printf(" Size Used Avail (root) %%Capacity\n"); - printf("%7sB %7sB %7sB %7sB %3llu%%\n", - s_total, s_used, s_avail, s_root, - (unsigned long long)(100 * (st.f_blocks - st.f_bfree) / - st.f_blocks)); + printf("%7sB %7sB %7sB %7sB %s\n", + s_total, s_used, s_avail, s_root, s_dcapacity); } else { printf(" Size Used Avail " "(root) %%Capacity\n"); - printf("%12llu %12llu %12llu %12llu %3llu%%\n", + printf("%12llu %12llu %12llu %12llu %s\n", (unsigned long long)(st.f_frsize * st.f_blocks / 1024), (unsigned long long)(st.f_frsize * (st.f_blocks - st.f_bfree) / 1024), (unsigned long long)(st.f_frsize * st.f_bavail / 1024), (unsigned long long)(st.f_frsize * st.f_bfree / 1024), - (unsigned long long)(100 * (st.f_blocks - st.f_bfree) / - st.f_blocks)); + s_dcapacity); } return 0; }