
We are using this function from base in Darcs in a way that causes trouble: the returned file handle is closed immediately and only the filename is passed on. Then the file gets re-opened and closed again and some time later deleted. If openBinaryTempFile is used in this way a few times in a row, it returns the same file name every time. I tested this with a small test program. My question: is openBinaryTempFile supposed to behave like that (if used in this way)? I am testing this on an ubuntu trusty with ghc-7.6.3, meaning base-4.6.0.1. Has the function been changed in later versions? Cheers Ben -- "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult." ― C.A.R. Hoare

If openBinaryTempFile is used in this way a few times in a row, it returns the same file name every time.
A quick inspection of the [source code][1] reveals that it uses the process ID (PID) to generate the initial filename of the temporary file. If the file already exists, the number is incremented until a new file is created. So the current implementation does in fact have this predictable behavior. I don't *think* this is insecure (but don't quote me on that), since `O_EXCL` is used to create the file, but it may be somewhat inefficient if there are a many files being created by one process or if processes with similar IDs create temporary files with this method. [1]: http://hackage.haskell.org/package/base-4.7.0.2/docs/src/System-IO.html#line...

Phil Ruffwind wrote:
If openBinaryTempFile is used in this way a few times in a row, it returns the same file name every time.
A quick inspection of the [source code][1] reveals that it uses the process ID (PID) to generate the initial filename of the temporary file. If the file already exists, the number is incremented until a new file is created. So the current implementation does in fact have this predictable behavior.
I don't *think* this is insecure (but don't quote me on that), since `O_EXCL` is used to create the file, but it may be somewhat inefficient if there are a many files being created by one process or if processes with similar IDs create temporary files with this method.
Thanks for digging it up. I don't think it is insecure, I guess our code just makes a wrong assumption (somewhere) about the file name being unique when it cleans up afterwards. Cheers Ben -- "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult." ― C.A.R. Hoare

Ben Franksen wrote:
Phil Ruffwind wrote:
If openBinaryTempFile is used in this way a few times in a row, it returns the same file name every time.
A quick inspection of the [source code][1] reveals that it uses the process ID (PID) to generate the initial filename of the temporary file. If the file already exists, the number is incremented until a new file is created. So the current implementation does in fact have this predictable behavior.
I don't *think* this is insecure (but don't quote me on that), since `O_EXCL` is used to create the file, but it may be somewhat inefficient if there are a many files being created by one process or if processes with similar IDs create temporary files with this method.
Thanks for digging it up. I don't think it is insecure, I guess our code just makes a wrong assumption (somewhere) about the file name being unique when it cleans up afterwards.
A quick follow-up on this: It turned out that the non-unique file names were a red herring. What really caused the trouble was that -- despite clear warnings in the docs not to do so -- we used CatchT on top of IO and then used the Control.Monad.Catch.bracket operator in place of the one from Control.Exception, thinking that this would still ensure proper cleanup of the temporary file. It does not (as the docs for MonadCatch explain in detail). Lesson: Heed the warnings in the documentation! They are there for a reason. Cheers Ben -- "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult." ― C.A.R. Hoare
participants (2)
-
Ben Franksen
-
Phil Ruffwind