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

NetBSD Home
NetBSD PR Database Search

(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.