From f434ff8dac4e8236369df86f30dbceb6c11d33a5 Mon Sep 17 00:00:00 2001 From: Etienne Millon Date: Wed, 17 Apr 2024 14:22:28 +0200 Subject: [PATCH] [3.15] backport #10333 (#10431) * test: demonstrate overflow with sendfile (#10334) See #10333 Signed-off-by: Etienne Millon * fix: use `Long_val` for sendfile() parameters to fix file copying in docker (#10333) * fix: sendfile() in docker Signed-off-by: Haoxiang Fei * use ssize_t for return value Co-authored-by: Etienne Millon Signed-off-by: Haoxiang Fei * update test Signed-off-by: Etienne Millon * Add changelog Signed-off-by: Etienne Millon --------- Signed-off-by: Haoxiang Fei Signed-off-by: Haoxiang Fei Signed-off-by: Etienne Millon Co-authored-by: Etienne Millon Co-authored-by: Etienne Millon * fix formatting (#10356) Signed-off-by: Etienne Millon * move changelog entry to the right place (#10375) Signed-off-by: Etienne Millon --------- Signed-off-by: Etienne Millon Signed-off-by: Haoxiang Fei Signed-off-by: Haoxiang Fei Co-authored-by: Haoxiang Fei --- doc/changes/10333.md | 2 ++ otherlibs/stdune/src/copyfile_stubs.c | 6 ++--- test/blackbox-tests/test-cases/dune | 8 +++++++ .../test-cases/sendfile-large-file.t | 22 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 doc/changes/10333.md create mode 100644 test/blackbox-tests/test-cases/sendfile-large-file.t diff --git a/doc/changes/10333.md b/doc/changes/10333.md new file mode 100644 index 00000000000..94555138246 --- /dev/null +++ b/doc/changes/10333.md @@ -0,0 +1,2 @@ +- fix overflow in sendfile stubs (copy of large files could fail or end with + truncated files) (#10333, @tonyfettes) diff --git a/otherlibs/stdune/src/copyfile_stubs.c b/otherlibs/stdune/src/copyfile_stubs.c index 09c9a1b140a..4ab47f35c19 100644 --- a/otherlibs/stdune/src/copyfile_stubs.c +++ b/otherlibs/stdune/src/copyfile_stubs.c @@ -73,8 +73,8 @@ CAMLprim value stdune_copyfile(value v_from, value v_to) { caml_failwith("copyfile: only on macos"); } -static int dune_sendfile(int in, int out, int length) { - int ret; +static int dune_sendfile(int in, int out, size_t length) { + ssize_t ret; while (length > 0) { ret = sendfile(out, in, NULL, length); if (ret < 0) { @@ -90,7 +90,7 @@ CAMLprim value stdune_sendfile(value v_in, value v_out, value v_size) { caml_release_runtime_system(); /* TODO Use copy_file_range once we have a good mechanism to test for its * existence */ - int ret = dune_sendfile(FD_val(v_in), FD_val(v_out), Int_val(v_size)); + int ret = dune_sendfile(FD_val(v_in), FD_val(v_out), Long_val(v_size)); caml_acquire_runtime_system(); if (ret < 0) { uerror("sendfile", Nothing); diff --git a/test/blackbox-tests/test-cases/dune b/test/blackbox-tests/test-cases/dune index 5457f0c02ea..a90bb873a78 100644 --- a/test/blackbox-tests/test-cases/dune +++ b/test/blackbox-tests/test-cases/dune @@ -43,6 +43,14 @@ (applies_to fdo) (enabled_if false)) +; This test copies a large file, which is too slow to be enabled all the time. +; The source file is actually sparse, but sendfile seems to do a full copy +; nevertheless. + +(cram + (applies_to sendfile-large-file) + (enabled_if false)) + ; This test is flaky (cram diff --git a/test/blackbox-tests/test-cases/sendfile-large-file.t b/test/blackbox-tests/test-cases/sendfile-large-file.t new file mode 100644 index 00000000000..c7b1cd860e2 --- /dev/null +++ b/test/blackbox-tests/test-cases/sendfile-large-file.t @@ -0,0 +1,22 @@ +We create a large file and check that it is copied completely. + + $ cat > dune-project << EOF + > (lang dune 1.0) + > EOF + + $ cat > create.ml << EOF + > let () = Unix.truncate "file.dat" 0x1_00_00_00_03 + > EOF + $ touch file.dat + $ ocaml unix.cma create.ml + $ rm create.ml + + $ dune build file.dat + + $ dune_cmd stat size file.dat + 4294967299 + + $ dune_cmd stat size _build/default/file.dat + 4294967299 + +(3 indicates that the file size is taken modulo 2**32)