Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lwt_io.open_file: Unix.O_TRUNC is a dangerous default for output channel #570

Closed
StrykerKKD opened this issue Apr 5, 2018 · 9 comments
Closed
Labels
Milestone

Comments

@StrykerKKD
Copy link

I think O_TRUNC is a little bit dangerous default, because the output channel modifies the file's content by just opening it. For me it's feels like an unexpected side effect. This behavior is also not documented, which made it harder to find out why my file kept getting truncated.

@aantron
Copy link
Collaborator

aantron commented Apr 5, 2018

Agreed.

I'm not sure what the best way to address this is, though. O_TRUNC is pretty typical for many usages, and not supplying it by default can result in a surprising coeffect, files that are too large and contain unexpected (old) data. Perhaps this should only be clearly and loudly documented?

@StrykerKKD
Copy link
Author

I think only the docs should be updated, because removing O_TRUNC cold be a big breaking change for a such a small "improvement".

@aantron aantron closed this as completed in f5577c3 Apr 5, 2018
@aantron
Copy link
Collaborator

aantron commented Apr 5, 2018

Ok, docs included in the commit linked above. Hopefully, that is good enough to resolve this.

Thinking about it more, it seems best to keep O_TRUNC, not only because of breakage if we remove it. Without O_TRUNC, all existing and future instances of ordinary code like this:

Lwt_io.with_file ~mode:Output "foo" (fun channel ->
  Lwt_io.write ...)

...which are naively expected to leave foo in a predictable state, become incorrect. In the worst case, they become security vulnerabilities. I think O_TRUNC is the right default, otherwise we have an API that is too difficult to intuitively use safely, i.e. a broken API.

That said, it is still true that O_TRUNC is a surprising side effect when it is unwanted, so we do have to document it :)

@hcarty
Copy link
Contributor

hcarty commented Feb 27, 2019

I ran into this recently. I wonder if it would be reasonable to make flags a required argument in a future, major release. That way the user is forced to decide which behavior they want.

@aantron
Copy link
Collaborator

aantron commented Feb 28, 2019

I just searched packages that depend on Lwt in opam. At least the following packages would be affected by making this change: biocaml, cohttp, csv, csvprovider, dns-forward, flow, future, imap, imaplet-lwt, lambda-term, markup, mechaml, message-switch, mirror, plotkicadsch, pvem_lwt_unix.

I'm not certain if its worth doing, but I would like to do it.

@aantron aantron reopened this Feb 28, 2019
@aantron aantron added this to the 5.0.0 milestone Jul 27, 2019
@aantron
Copy link
Collaborator

aantron commented Jul 27, 2019

If we only make ~flags required, the interface becomes a bit awkward. In

val open_file :
  ?buffer:Lwt_bytes.t ->
  flags:Unix.open_flag list ->
  ?perm:Unix.file_perm ->
  mode:'a mode ->
  file_name ->
    'a channel Lwt.t

the user would have to specify both ~flags:[O_RDONLY] and ~mode:Input, which seems redundant. Perhaps we should then have the ~mode argument add O_RDONLY to the list, if it or O_RDWR is not already present?

Another option might be to switch from using the Unix flags to a GADT, where the constructors O_RDONLY and O_WRONLY specify the phantom types input and output. Then, we can drop ~mode entirely. This would break even more users, though, as it would affect everyone.

@aantron aantron modified the milestones: 5.0.0, 4.3.0 Aug 3, 2019
@aantron
Copy link
Collaborator

aantron commented Aug 5, 2019

We decided to close this again. A better API can be made than the existing openfile, but it's difficult to gradually change openfile into it:

  • Making ~flags required breaks only some users, but the result is an awkward API, perhaps not worth the breakage.
  • Changing openfile more thoroughly breaks all users.

So, it seems best to keep the flaws of openfile in mind if/when designing a replacement API, but leave the current openfile alone.

@aantron aantron closed this as completed Aug 5, 2019
@hcarty
Copy link
Contributor

hcarty commented Aug 5, 2019

From an separate discussion with @aantron - A useful longer term plan could be to create a Lwt equivalent of bos. Specifically the Bos.OS portion of the library.

That work could be done separately from core Lwt. If there's demand the code could be proposed for inclusion in Lwt itself.

@raphael-proust
Copy link
Collaborator

@hcarty feedback on this early prototype is welcome: https://gitlab.com/raphael-proust/boloss
(Although this thread is maybe not the most appropriate place to discuss this library, I put the call here so it can be found easily.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants