The leak reported by Igor is in opentemp().
The only place opentemp() is called from is diffreg().

When diffreg() is called from main(), the only calls that
follow are print_status() and exit(), so we do not really
leak anything:  opentemp() "leaks" ifd, returns NULL,
diffreg() returns, main() calls print_status() and exit().

>From diffdir(), diffreg() is only called for regular files,
and in that case, it never calls opentemp(), so the "leak"
cannot happen with diff -r.

There is no other place diffreg() is called from.

I doubt that we may ever want to change the above.  Recursively
diffing directories containing special files by first copying
them to temp files using the read(2)-write(2)-loop in opentemp()
does not look like it might ever become a sane idea.

So i conclude the code is correct, and can't see how it risks
to become incorrect by changing it, unless the changes are
insane for unrelated reasons.

This analysis is a bit involved, so i guess we want to commit
the fix anyway?  Just to make correctness of the code more obvious.

As whitespace in the original diff was mangled - two blanks
before leading tabs - here is a version that applies.

The following exercises the code path in question,
showing that both versions work as expected:

  schwa...@rhea $ export TMPDIR=/nonexistent     
  schwa...@rhea $ diff /dev/null /dev/null       
  diff: /dev/null: No such file or directory
  schwa...@rhea $ echo $?
  2
  schwa...@rhea $ ./obj/diff /dev/null /dev/null 
  diff: /dev/null: No such file or directory
  schwa...@rhea $ echo $?                        
  2

By the way, "/dev/null: No such file or directory"
looks funny, what actually fails is
  mkstemp("/nonexistent/diff.XXXXXXXX")
of course.


Index: diffreg.c
===================================================================
RCS file: /cvs/src/usr.bin/diff/diffreg.c,v
retrieving revision 1.73
diff -u -p -r1.73 diffreg.c
--- diffreg.c   27 Oct 2009 23:59:37 -0000      1.73
+++ diffreg.c   22 Mar 2010 01:21:16 -0000
@@ -514,8 +514,10 @@ opentemp(const char *file)
                return (NULL);
        }
 
-       if ((ofd = mkstemp(tempfile)) < 0)
+       if ((ofd = mkstemp(tempfile)) < 0) {
+               close(ifd);
                return (NULL);
+       }
        unlink(tempfile);
        while ((nread = read(ifd, buf, BUFSIZ)) > 0) {
                if (write(ofd, buf, nread) != nread) {

Reply via email to