From 97a3a8cb6718ebcff86976c8cf1ebf8d8c1ee81a Mon Sep 17 00:00:00 2001 From: K900 Date: Fri, 18 Jul 2025 10:19:01 +0300 Subject: [PATCH] readFile: don't explode on negative st_size Should this ever happen? No. Does it? Evidently. Change-Id: I62fa7530fbc2cdfd6112088dbc82a4a615cf6820 --- lix/libutil/file-descriptor.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lix/libutil/file-descriptor.cc b/lix/libutil/file-descriptor.cc index 2a8dab3e2..296837be9 100644 --- a/lix/libutil/file-descriptor.cc +++ b/lix/libutil/file-descriptor.cc @@ -21,7 +21,20 @@ std::string readFile(int fd) if (fstat(fd, &st) == -1) throw SysError("statting file"); - return drainFD(fd, true, st.st_size); + // st_size is off_t, which is signed for some reason, and there doesn't + // seem to be any rule stating that it _can't_ return a negative value. + // + // So, when a filesystem returns a small negative value for whatever reason, + // we cast it to unsigned and then try to preallocate ALL THE MEMORY, + // which, of course, explodes horribly and very user-unfriendly-ly. + // + // This should really just be a `saturate_cast`, which does exactly + // what we want (clamp to 0..TargetT::MAX if out of range), + // but that's C++26, so we can't have nice things yet, and are + // forced to roll out own, bad one. + // + // FIXME(C++26): use saturate_cast. + return drainFD(fd, true, (size_t) std::max((off_t) 0, st.st_size)); }