From nobody@FreeBSD.org  Wed Oct 11 13:02:33 2006
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id EC77B16A403
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Oct 2006 13:02:33 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 29DA743D62
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Oct 2006 13:02:29 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k9BD2T3u024343
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Oct 2006 13:02:29 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id k9BD2SbI024342;
	Wed, 11 Oct 2006 13:02:28 GMT
	(envelope-from nobody)
Message-Id: <200610111302.k9BD2SbI024342@www.freebsd.org>
Date: Wed, 11 Oct 2006 13:02:28 GMT
From: trasz<trasz@pin.if.uz.zgora.pl>
To: freebsd-gnats-submit@FreeBSD.org
Subject: freopen(NULL, ...) does bad things to file offset.
X-Send-Pr-Version: www-3.0

>Number:         104295
>Category:       bin
>Synopsis:       freopen(NULL, ...) does bad things to file offset.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 11 13:10:17 GMT 2006
>Closed-Date:    Sat Nov 18 21:24:37 GMT 2006
>Last-Modified:  Sat Nov 18 21:24:37 GMT 2006
>Originator:     trasz
>Release:        6.1
>Organization:
>Environment:
FreeBSD traszkan.ds7 6.2-PRERELEASE FreeBSD 6.2-PRERELEASE #1: Fri Sep 29 12:04:37 CEST 2006     trasz@traszkan.ds7:/usr/obj/usr/src/sys/TRASHCAN  i386
>Description:
Freopen(3) does bad things to the file offset when supplied with NULL
as a file path (freopen(NULL, mode, fd);).  The test program below returns:

file offset before freopen is 100.
file offset after freopen is 2399.

>How-To-Repeat:
#include <stdio.h>

int main(void)
{
        int ret;
        FILE *f;

        f=fopen("/etc/passwd", "r");
        if (f==NULL) {
                perror("fopen");
                exit(-1);
        }

        ret=fseek(f, 100, SEEK_CUR);
        if (ret<0) {
                perror("fseek");    
                exit(-1);
        }

        ret=ftell(f);
        fprintf(stderr, "file offset before freopen is %d.\n", ret);

        f=freopen(NULL, "r", f);
        if (f==NULL) {
                perror("freopen");
                exit(-1);
        }

        ret=ftell(f);
        fprintf(stderr, "file offset after freopen is %d.\n", ret);

        return 0;
}

>Fix:
NOT TESTED:

--- freopen.c.orig      Wed Oct 11 14:59:25 2006
+++ freopen.c   Wed Oct 11 15:00:47 2006
@@ -217,5 +217,9 @@
        fp->_seek = __sseek;
        fp->_close = __sclose;
        FUNLOCKFILE(fp);
+
+       if (file == NULL)
+               rewind(fp);
+
        return (fp);
 }

>Release-Note:
>Audit-Trail:

From: Ruslan Ermilov <ru@FreeBSD.org>
To: trasz <trasz@pin.if.uz.zgora.p>
Cc: bug-followup@FreeBSD.org, Andrey Chernov <ache@nagual.pp.ru>
Subject: Re: bin/104295: freopen(NULL, ...) does bad things to file offset.
Date: Wed, 11 Oct 2006 21:14:44 +0400

 On Wed, Oct 11, 2006 at 01:02:28PM +0000, trasz wrote:
 > Freopen(3) does bad things to the file offset when supplied with NULL
 > as a file path (freopen(NULL, mode, fd);).  The test program below returns:
 > 
 > file offset before freopen is 100.
 > file offset after freopen is 2399.
 > 
 It's actually the minimum of a pagesize and file size.  Now we know
 the size of your /etc/passwd.  :-)
 
 > #include <stdio.h>
 > 
 > int main(void)
 > {
 >         int ret;
 >         FILE *f;
 > 
 >         f=fopen("/etc/passwd", "r");
 >         if (f==NULL) {
 >                 perror("fopen");
 >                 exit(-1);
 >         }
 > 
 >         ret=fseek(f, 100, SEEK_CUR);
 >         if (ret<0) {
 >                 perror("fseek");    
 >                 exit(-1);
 >         }
 > 
 >         ret=ftell(f);
 >         fprintf(stderr, "file offset before freopen is %d.\n", ret);
 > 
 >         f=freopen(NULL, "r", f);
 >         if (f==NULL) {
 >                 perror("freopen");
 >                 exit(-1);
 >         }
 > 
 >         ret=ftell(f);
 >         fprintf(stderr, "file offset after freopen is %d.\n", ret);
 > 
 >         return 0;
 > }
 > 
 It's only a problem when a file was initially opened read-only;
 if you open it "r+" the problem doesn't show up.
 
 I don't know the stdio code very well, but I tracked it down to
 optimizations in _fseeko(); basically, freopen() calls
 _fseeko(fp, 0, SEEK_SET, 0) and that's getting optimized by not
 doing a real seek and simply adjusting the pointers.  Later in
 freopen(), these pointers get reset but the underlying file in
 question stays at its old position.  I've worked around this
 by temporarily disabling the fseek() optimization:
 
 %%%
 Index: freopen.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/freopen.c,v
 retrieving revision 1.13
 diff -u -p -r1.13 freopen.c
 --- freopen.c	22 May 2004 15:19:41 -0000	1.13
 +++ freopen.c	11 Oct 2006 17:01:00 -0000
 @@ -115,6 +115,7 @@ freopen(file, mode, fp)
  		}
  		if (oflags & O_TRUNC)
  			ftruncate(fp->_file, 0);
 +		fp->_flags |= __SNPT;
  		if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
  		    0) < 0 && errno != ESPIPE) {
  			sverrno = errno;
 %%%
 
 Someone with more stdio-fu should pick it up.  Andrey?
 
 
 Cheers,
 -- 
 Ruslan Ermilov
 ru@FreeBSD.org
 FreeBSD committer
State-Changed-From-To: open->patched 
State-Changed-By: ache 
State-Changed-When: Sun Oct 15 16:25:20 UTC 2006 
State-Changed-Why:  
Fixed in -current 

http://www.freebsd.org/cgi/query-pr.cgi?pr=104295 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/104295: commit references a PR
Date: Sun, 15 Oct 2006 16:24:50 +0000 (UTC)

 ache        2006-10-15 16:24:31 UTC
 
   FreeBSD src repository
 
   Modified files:
     lib/libc/stdio       freopen.c 
   Log:
   Do real seek
   Catch ftruncate errors
   
   PR:             104295
   Submitted by:   ru (seek)
   
   Revision  Changes    Path
   1.14      +11 -3     src/lib/libc/stdio/freopen.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: ache 
State-Changed-When: Sat Nov 18 21:24:15 UTC 2006 
State-Changed-Why:  
Committed into -stable 

http://www.freebsd.org/cgi/query-pr.cgi?pr=104295 
>Unformatted:
