aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2022-01-06 01:20:12 +0100
committerRobert Hensing <robert@roberthensing.nl>2022-01-19 15:21:56 +0100
commitd038a67bd3c6ed0d6452d595cf0af3115e14c48f (patch)
tree38d423aa4332d1050a466adeb1b21af194cb36fc /src
parentbc443511eb65420b51d10708e25427fe50de37a8 (diff)
Fix segfault or stack overflow caused by large derivation fields
This removes a dynamic stack allocation, making the derivation unparsing logic robust against overflows when large strings are added to a derivation. Overflow behavior depends on the platform and stack configuration. For instance, x86_64-linux/glibc behaves as (somewhat) expected: $ (ulimit -s 20000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix) error: stack overflow (possible infinite recursion) $ (ulimit -s 40000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix) error: expression does not evaluate to a derivation (or a set or list of those) However, on aarch64-darwin: $ nix-instantiate big-attr.nix ~ zsh: segmentation fault nix-instantiate big-attr.nix This indicates a slight flaw in the single stack protection page approach that is not encountered with normal stack frames.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/derivations.cc10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index b926bb711..616e78076 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -272,7 +272,15 @@ Derivation parseDerivation(const Store & store, std::string && s, std::string_vi
static void printString(string & res, std::string_view s)
{
- char buf[s.size() * 2 + 2];
+ char * buf;
+ size_t bufSize = s.size() * 2 + 2;
+ std::unique_ptr<char[]> dynBuf;
+ if (bufSize < 0x10000) {
+ buf = (char *)alloca(bufSize);
+ } else {
+ dynBuf = decltype(dynBuf)(new char[bufSize]);
+ buf = dynBuf.get();
+ }
char * p = buf;
*p++ = '"';
for (auto c : s)