diff options
author | Lulu <lulu.berlin.2023@gmail.com> | 2024-10-07 09:43:30 +0200 |
---|---|---|
committer | Lulu <lulu.berlin.2023@gmail.com> | 2024-10-08 01:26:30 +0200 |
commit | 51a5025913cd2c901203e1a8d8f8a0df1c1a130b (patch) | |
tree | 31b6b3b84c745d46b2a3684ab312a73df6580af0 | |
parent | ed9b7f4f84fd60ad8618645cc1bae2d686ff0db6 (diff) |
Avoid calling memcpy when len == 0 in filetransfer.cc
There was a bug report about a potential call to `memcpy` with a null
pointer which is not reproducible:
https://git.lix.systems/lix-project/lix/issues/492
This occurred in `src/libstore/filetransfer.cc` in `InnerSource::read`.
To ensure that this doesn't happen, an early return is added before
calling `memcpy` if the length of the data to be copied is 0.
This change also adds a test that ensures that when `InnerSource::read`
is called with an empty file, it throws an `EndOfFile` exception.
Change-Id: Ia18149bee9a3488576c864f28475a3a0c9eadfbb
-rw-r--r-- | src/libstore/filetransfer.cc | 5 | ||||
-rw-r--r-- | tests/unit/libstore/filetransfer.cc | 8 |
2 files changed, 12 insertions, 1 deletions
diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 6fe1f9a05..34b92148e 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -6,6 +6,7 @@ #include "signals.hh" #include "compression.hh" #include "strings.hh" +#include <cstddef> #if ENABLE_S3 #include <aws/core/client/ClientConfiguration.h> @@ -784,8 +785,10 @@ struct curlFileTransfer : public FileTransfer size_t read(char * data, size_t len) override { - auto readPartial = [this](char * data, size_t len) { + auto readPartial = [this](char * data, size_t len) -> size_t { const auto available = std::min(len, buffered.size()); + if (available == 0u) return 0u; + memcpy(data, buffered.data(), available); buffered.remove_prefix(available); return available; diff --git a/tests/unit/libstore/filetransfer.cc b/tests/unit/libstore/filetransfer.cc index 71e7392fc..fd4d326f0 100644 --- a/tests/unit/libstore/filetransfer.cc +++ b/tests/unit/libstore/filetransfer.cc @@ -150,6 +150,14 @@ TEST(FileTransfer, exceptionAbortsDownload) } } +TEST(FileTransfer, exceptionAbortsRead) +{ + auto [port, srv] = serveHTTP("200 ok", "content-length: 0\r\n", [] { return ""; }); + auto ft = makeFileTransfer(); + char buf[10] = ""; + ASSERT_THROW(ft->download(FileTransferRequest(fmt("http://[::1]:%d/index", port)))->read(buf, 10), EndOfFile); +} + TEST(FileTransfer, NOT_ON_DARWIN(reportsSetupErrors)) { auto [port, srv] = serveHTTP("404 not found", "", [] { return ""; }); |