Stack overflow when builtins.toXML is given a derivation

#397
Opened by qyliss at 2024-04-09T09·57+00

builtins.toXML {                     
  drv = derivation {
    name = "test";
    builder = "/bin/sh";
    system = builtins.currentSystem;
  };
}

cppnix:

<?xml version='1.0' encoding='utf-8'?>
<expr>
  <attrs>
    <attr name="drv">
      <derivation drvPath="/nix/store/vbmz3fr4imxm4r227b0jxz3izav4cdm0-test.drv" outPath="/nix/store/a3b6sypggf9c6qama5j182zsm6vcb2s5-test">
        <attr name="all">
          <list>
            <derivation drvPath="/nix/store/vbmz3fr4imxm4r227b0jxz3izav4cdm0-test.drv" outPath="/nix/store/a3b6sypggf9c6qama5j182zsm6vcb2s5-test">
              <repeated />
            </derivation>
          </list>
        </attr>
        <attr name="builder">
          <string value="/bin/sh" />
        </attr>
        <attr name="drvAttrs">
          <attrs>
            <attr name="builder">
              <string value="/bin/sh" />
            </attr>
            <attr name="name">
              <string value="test" />
            </attr>
            <attr name="system">
              <string value="aarch64-linux" />
            </attr>
          </attrs>
        </attr>
        <attr name="drvPath">
          <string value="/nix/store/vbmz3fr4imxm4r227b0jxz3izav4cdm0-test.drv" />
        </attr>
        <attr name="name">
          <string value="test" />
        </attr>
        <attr name="out">
          <derivation drvPath="/nix/store/vbmz3fr4imxm4r227b0jxz3izav4cdm0-test.drv" outPath="/nix/store/a3b6sypggf9c6qama5j182zsm6vcb2s5-test">
            <repeated />
          </derivation>
        </attr>
        <attr name="outPath">
          <string value="/nix/store/a3b6sypggf9c6qama5j182zsm6vcb2s5-test" />
        </attr>
        <attr name="outputName">
          <string value="out" />
        </attr>
        <attr name="system">
          <string value="aarch64-linux" />
        </attr>
        <attr name="type">
          <string value="derivation" />
        </attr>
      </derivation>
    </attr>
  </attrs>
</expr>

tvix:

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

  1. Nix must have some special support for derivations here, because they seem to have cycles, which our toXML implementation does not recognize (though the repl does). A large-but-terminating expression like this does still lead to a stack overflow though:

    let fix = f: let x = f x; in x; in builtins.toXML (fix (f: i: if i >10000 then {} else { "${toString i}" = f (i + 1); }) 0)
    

    It does not seem to do so in nix-repl (though if you increase the loop breaker constant any more, you risk blowing out all your memory …)

    profpatsch at 2024-05-20T20·49+00

  2. With my changes in https://cl.tvl.fyi/c/depot/+/11698, the following expression:

    let fix = f: let x = f x; in x; in builtins.substring 0 100 (builtins.toXML (fix (f: i: if i >20000 then {} else { "${toString i}" = f (i + 1); }) 0))
    

    takes ~10s in nix repl and ~20s in tvix repl.

    profpatsch at 2024-05-20T21·04+00