Skip to content

Commit

Permalink
Prevent seek_in from marking buffer data as valid after closing the…
Browse files Browse the repository at this point in the history
… channel (ocaml#11965)

* Test calls to input_byte after close_in

Add a test demonstrating issue ocaml#11878

* Reset offset when closing a channel

If offset keeps its value when the channel is closed, it is possible to
`seek_in` backward which will only decrease `channel->curr` and therefore
mark some buffer bytes as valid: further calls to `input_byte` would
succeed on the closed channel

Fixes: ocaml#11878
  • Loading branch information
shym committed Feb 7, 2023
1 parent 8197ebb commit a606e92
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ Working version
with examples and sections to group related functions.
(Kiran Gopinathan, review by Daniel Bünzli and Xavier Leroy)

- #11878, #11965: Prevent seek_in from marking buffer data as valid after
closing the channel. This could lead to inputting uninitialized bytes.
(Samuel Hym, review by Xavier Leroy and Olivier Nicole)

- #11848: Add `List.find_mapi`, `List.find_index`, `Seq.find_mapi`,
`Seq.find_index`, `Array.find_mapi`, `Array.find_index`,
`Float.Array.find_opt`, `Float.Array.find_index`, `Float.Array.find_map`,
Expand Down
3 changes: 3 additions & 0 deletions runtime/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,9 @@ CAMLprim value caml_ml_close_channel(value vchannel)
immediate caml_flush_partial or caml_refill, thus raising a Sys_error
exception */
channel->curr = channel->max = channel->end;
/* Prevent any seek backward that would mark the last bytes of the
* channel buffer as valid */
channel->offset = 0;

/* If already closed, we are done */
if (channel->fd != -1) {
Expand Down
20 changes: 20 additions & 0 deletions testsuite/tests/lib-channels/close_in.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(* TEST *)

(* Test that inputting bytes from a closed in_channel triggers an exception *)

(* The number of bytes we'll rewind after closing; a value
between 1 and IO_BUFFER_SIZE *)
let nb_bytes = 3

let () =
let ic = open_in_bin Sys.argv.(0) in
seek_in ic nb_bytes;
close_in ic;
seek_in ic 0;
assert (
try
ignore (input_byte ic);
false
with
| Sys_error _ -> true
| _ -> false)

0 comments on commit a606e92

Please sign in to comment.