NetBSD Problem Report #48183
From www@NetBSD.org Wed Sep 4 23:27:50 2013
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
(Client CN "mail.NetBSD.org", Issuer "Postmaster NetBSD.org" (verified OK))
by mollari.NetBSD.org (Postfix) with ESMTPS id B33B270836
for <gnats-bugs@gnats.NetBSD.org>; Wed, 4 Sep 2013 23:27:50 +0000 (UTC)
Message-Id: <20130904232749.5EDFE710DA@mollari.NetBSD.org>
Date: Wed, 4 Sep 2013 23:27:49 +0000 (UTC)
From: manuel@bsdstammtisch.at
Reply-To: manuel@bsdstammtisch.at
To: gnats-bugs@NetBSD.org
Subject: Example in man write(2) causes endless loop
X-Send-Pr-Version: www-1.0
>Number: 48183
>Category: bin
>Synopsis: Example in man write(2) causes endless loop
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: doc-bug
>Submitter-Id: net
>Arrival-Date: Wed Sep 04 23:30:00 +0000 2013
>Last-Modified: Thu Sep 05 23:45:01 +0000 2013
>Originator: Manuel Wiesinger
>Release: 6.99.23
>Organization:
>Environment:
NetBSD scampi 6.99.23 NetBSD 6.99.23 (GENERIC) #0: Fri Jul 19 21:47:43 CEST 2013 manuel@scampi:/usr/obj/sys/arch/amd64/compile/GENERIC amd64
>Description:
The manpage of pread says:
Proper loops should use
while ((nr = write(fd, buf, sizeof(buf))) != -1 && nr != 0)
which is clearly an endless loop. Say nr = 512 and the write is successful, then 512 != -1 && n1 !=0 is true.
>How-To-Repeat:
Compile this C program:
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main()
{
off_t blk, new_blk;
ssize_t w;
char buf[] = "heydo";
int fd = open("/tmp/test", O_WRONLY | O_CREAT);
while ((w = write(fd, buf, sizeof(buf))) != -1 && w != 0)
printf("w: %ld\n", w);
return 1;
}
>Fix:
Suggest something like the following.
When zero bytes have been written, or the write has failed error handling is necessary.
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main()
{
off_t blk, new_blk;
ssize_t w;
char buf[] = "heydo";
int fd = open("/tmp/test", O_WRONLY | O_CREAT);
while ((w = write(fd, buf, sizeof(buf))) != sizeof(buf)) {
if(w == 0 || w == -1)
errx(EXIT_FAILURE, "could not write\n");
}
return 1;
}
>Audit-Trail:
From: David Laight <david@l8s.co.uk>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/48183: Example in man write(2) causes endless loop
Date: Thu, 5 Sep 2013 08:10:23 +0100
On Wed, Sep 04, 2013 at 11:30:00PM +0000, manuel@bsdstammtisch.at wrote:
> >Number: 48183
> >Category: bin
> >Synopsis: Example in man write(2) causes endless loop
...
> The manpage of pread says:
>
> Proper loops should use
> while ((nr = write(fd, buf, sizeof(buf))) != -1 && nr != 0)
>
> which is clearly an endless loop. Say nr = 512 and the write is
> successful, then 512 != -1 && n1 !=0 is true.
That whole section is fud.
It would only ever be a problem if the program had a buffer large enough.
That is a 2GB buffer on a system with 32bit size_t!
The application would also know that it was doing very large writes.
In most programs the write() calls are small (relative to size_t).
I suspect it is only a problem for systems with 16bit size_t and 32bit ptr.
The 'partial write' support would be more useful - especially for writev().
David
--
David Laight: david@l8s.co.uk
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/48183: Example in man write(2) causes endless loop
Date: Fri, 6 Sep 2013 03:41:52 +0400
> On Wed, Sep 04, 2013 at 11:30:00PM +0000, manuel@bsdstammtisch.at wrote:
> > >Number: 48183
> > >Category: bin
> > >Synopsis: Example in man write(2) causes endless loop
> ...
> > The manpage of pread says:
> >
> > Proper loops should use
> > while ((nr = write(fd, buf, sizeof(buf))) != -1 && nr != 0)
> >
> > which is clearly an endless loop. Say nr = 512 and the write is
> > successful, then 512 != -1 && n1 !=0 is true.
>
> That whole section is fud.
> It would only ever be a problem if the program had a buffer large enough.
> That is a 2GB buffer on a system with 32bit size_t!
> The application would also know that it was doing very large writes.
> In most programs the write() calls are small (relative to size_t).
> I suspect it is only a problem for systems with 16bit size_t and 32bit ptr.
>
> The 'partial write' support would be more useful - especially for writev().
The text is self-contradictory as using implementation-defined
behaviour (nbytes > SSZIZE_MAX) is not something you would do for
"maximum portability".
Manual should explicitly say that for nbytes > SSIZE_MAX the result is
implementation-defined.
Name of the "nr" variable suggests that the example was copy-pasted
from read(2), which is indeed the case. The loops, as written, don't
make much sense for write(2).
-uwe
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.