From 083828859c78b45271a1cd6f536adb9eab2b6add Mon Sep 17 00:00:00 2001 From: rillig Date: Thu, 14 Mar 2024 21:17:54 +0000 Subject: [PATCH] stat: don't allow numeric formatting flags on strings Calling snprintf with "%+s" invokes undefined behavior. --- tests/usr.bin/stat/t_stat.sh | 11 ++++++++--- usr.bin/stat/stat.c | 14 +++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/usr.bin/stat/t_stat.sh b/tests/usr.bin/stat/t_stat.sh index 51dbceff6400..b4bc56320d18 100644 --- a/tests/usr.bin/stat/t_stat.sh +++ b/tests/usr.bin/stat/t_stat.sh @@ -1,4 +1,4 @@ -# $NetBSD: t_stat.sh,v 1.1 2024/03/14 21:00:33 rillig Exp $ +# $NetBSD: t_stat.sh,v 1.2 2024/03/14 21:17:54 rillig Exp $ # # Copyright (c) 2024 The NetBSD Foundation, Inc. # All rights reserved. @@ -44,10 +44,15 @@ string_format_body() { atf_check -o 'inline:left-aligned <Ümläute >\n' \ stat -f 'left-aligned <%-20SN>' 'Ümläute' - # FIXME: invokes undefined behavior in snprintf "%+s" - atf_check -o 'inline:string-plus <Ümläute>\n' \ + atf_check -s exit:1 -o ignore -e 'inline:stat: % SN: bad format\n' \ + stat -f 'string-space <% SN>' 'Ümläute' + + atf_check -s exit:1 -o ignore -e 'inline:stat: %+SN: bad format\n' \ stat -f 'string-plus <%+SN>' 'Ümläute' + atf_check -s exit:1 -o ignore -e 'inline:stat: %0SN: bad format\n' \ + stat -f 'string-zero <%0SN>' 'Ümläute' + atf_check -o 'inline:vis <\303\234ml\303\244ute>\n' \ stat -f 'vis <%#SN>' 'Ümläute' diff --git a/usr.bin/stat/stat.c b/usr.bin/stat/stat.c index dafb5f5ead70..6d6bc100d8d8 100644 --- a/usr.bin/stat/stat.c +++ b/usr.bin/stat/stat.c @@ -1,4 +1,4 @@ -/* $NetBSD: stat.c,v 1.52 2024/03/14 19:38:56 kre Exp $ */ +/* $NetBSD: stat.c,v 1.53 2024/03/14 21:17:54 rillig Exp $ */ /* * Copyright (c) 2002-2011 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ #include #if !defined(lint) -__RCSID("$NetBSD: stat.c,v 1.52 2024/03/14 19:38:56 kre Exp $"); +__RCSID("$NetBSD: stat.c,v 1.53 2024/03/14 21:17:54 rillig Exp $"); #endif #if ! HAVE_NBTOOL_CONFIG_H @@ -1065,11 +1065,11 @@ format1(const struct stat *st, errx(1, "%.*s: bad format", (int)flen, fmt); } - /* - * If a subdatum was specified but not supported, or an output - * format was selected that is not supported, that's an error. - */ - if (hilo != 0 || (ofmt & formats) == 0) + if (hilo != 0 // subdatum not supported + || !(ofmt & formats) // output format not supported + || (ofmt == FMTF_STRING && flags & FLAG_SPACE) + || (ofmt == FMTF_STRING && flags & FLAG_PLUS) + || (ofmt == FMTF_STRING && flags & FLAG_ZERO)) errx(1, "%.*s: bad format", (int)flen, fmt); /*