stat: don't allow numeric formatting flags on strings

Calling snprintf with "%+s" invokes undefined behavior.
This commit is contained in:
rillig 2024-03-14 21:17:54 +00:00
parent 897cdf26ba
commit 083828859c
2 changed files with 15 additions and 10 deletions

View File

@ -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'

View File

@ -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 <sys/cdefs.h>
#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);
/*