From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from joooj.vinc17.net (joooj.vinc17.net [155.133.131.76]) by sourceware.org (Postfix) with ESMTPS id 8C7FF3858C50 for ; Sat, 18 Mar 2023 10:58:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8C7FF3858C50 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=vinc17.net Authentication-Results: sourceware.org; spf=none smtp.mailfrom=vinc17.net Received: from smtp-zira.vinc17.net (128.119.75.86.rev.sfr.net [86.75.119.128]) by joooj.vinc17.net (Postfix) with ESMTPSA id E326311D; Sat, 18 Mar 2023 11:58:27 +0100 (CET) Received: by zira.vinc17.org (Postfix, from userid 1000) id B3D822800183; Sat, 18 Mar 2023 11:58:27 +0100 (CET) Date: Sat, 18 Mar 2023 11:58:27 +0100 From: Vincent Lefevre To: Alejandro Colomar Cc: libc-alpha@sourceware.org, Stephan Bergmann , Paul Eggert , Simon Chopin , Andreas Schwab Subject: Re: UB status of snprintf on invalid ptr+size combination? Message-ID: <20230318105827.GB15308@zira.vinc17.org> Mail-Followup-To: Vincent Lefevre , Alejandro Colomar , libc-alpha@sourceware.org, Stephan Bergmann , Paul Eggert , Simon Chopin , Andreas Schwab References: <20230315123949.GC73312@zira.vinc17.org> <92810b6e-e7e6-6ffd-d33a-067b9f300059@redhat.com> <20230318020725.GA15308@zira.vinc17.org> <9c8cae93-cb8c-8689-1f0e-2b87514d3702@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <9c8cae93-cb8c-8689-1f0e-2b87514d3702@gmail.com> X-Mailer-Info: https://www.vinc17.net/mutt/ User-Agent: Mutt/2.2.9+69 (3263c953) vl-149028 (2023-03-13) X-Spam-Status: No, score=-1.6 required=5.0 tests=BAYES_00,KAM_DMARC_STATUS,KAM_LAZY_DOMAIN_SECURITY,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 2023-03-18 03:30:27 +0100, Alejandro Colomar wrote: > Hello Vincent, > > On 3/18/23 03:07, Vincent Lefevre wrote: > > On 2023-03-16 11:29:31 +0100, Stephan Bergmann wrote: > >> On 15/03/2023 13:39, Vincent Lefevre wrote: > >>> No, it is not obvious. If the C standard does not say that this is > >>> the size of the array, then it does not have to be the size of the > >>> array. The C standard just says: > >>> > >>> Otherwise, output characters beyond the n-1st are discarded rather > >>> than being written to the array, and a null character is written at > >>> the end of the characters actually written into the array. > >> > >> But in 7.1.4 "Use of library functions" the standard also says > >> > >>> If a function argument is described as being an array, the pointer > >>> passed to the function shall have a value such that all address > >>> computations and accesses to objects (that would be valid if the > >>> pointer did point to the first element of such an array) are > >>> valid. > >> > >> which could be construed as meaning that the n-1st array element must always > >> be accessible, even if a given invocation is known to always generate less > >> then n output characters. > > > > But the standard does not say that n is the size of the array. > > The size of the array could be the maximum of n and the size > > corresponding to the untruncated output string. > > I guess you mean the minimum? If it were the maximum, then it would > never truncate. Yes, obviously, the minimum. > [assuming you meant minimum]: > > As Andreas mentioned, that's valid for ISO C, but POSIX is more > restrictive. Here's a quote from fprintf(3posix): > > The snprintf() function shall be equivalent to sprintf(), with > the addition of the n argument which states the size of the > buffer referred to by s. > > It clearly specifies that 'n' is the size of the buffer, so > implementations are free to assume that `s+n` is a valid pointer. However, I'm wondering whether such a change is intentional. BTW, this description is even wrong: this is certainly not equivalent! If the untruncated output is larger than n, then the call is UB with sprintf(), while the output is truncated with snprintf(). What really occurs is described later, but still, this first sentence is incorrect. This could just mean that they tried to oversimplify when writing this text, without thinking of the details. > > Similarly, for strncpy, I would not see n as the size of the arrays, > > i.e. it is not allowed for the implementation to read characters > > past a null character (possibly unless this does not have unwanted > > effects), even though such characters would be among the first n > > characters. > > The size argument to strncpy(3) is the size of the destination buffer, > not the size of the input buffer. The input buffer must be either > a string, or a character sequence at least as large as the destination > buffer. Thus, in strncpy(3), reads are limited by > `strnlen(src, size)`, but writes are limited by `size`. I agree, but I was answering to Stephan Bergmann, who thought that a size_t argument could be seen as the size of the array arguments. IMHO, the (minimum) sizes of the arrays are just implied from the described behavior of the function. -- Vincent Lefèvre - Web: 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)