aboutsummaryrefslogtreecommitdiff
path: root/tests/functional/lang
AgeCommit message (Collapse)Author
2024-07-13language: cleanly ban integer overflowsJade Lovelace
This also bans various sneaking of negative numbers from the language into unsuspecting builtins as was exposed while auditing the consequences of changing the Nix language integer type to a newtype. It's unlikely that this change comprehensively ensures correctness when passing integers out of the Nix language and we should probably add a checked-narrowing function or something similar, but that's out of scope for the immediate change. During the development of this I found a few fun facts about the language: - You could overflow integers by converting from unsigned JSON values. - You could overflow unsigned integers by converting negative numbers into them when going into Nix config, into fetchTree, and into flake inputs. The flake inputs and Nix config cannot actually be tested properly since they both ban thunks, however, we put in checks anyway because it's possible these could somehow be used to do such shenanigans some other way. Note that Lix has banned Nix language integer overflows since the very first public beta, but threw a SIGILL about them because we run with -fsanitize=signed-overflow -fsanitize-undefined-trap-on-error in production builds. Since the Nix language uses signed integers, overflow was simply undefined behaviour, and since we defined that to trap, it did. Trapping on it was a bad UX, but we didn't even entirely notice that we had done this at all until it was reported as a bug a couple of months later (which is, to be fair, that flag working as intended), and it's got enough production time that, aside from code that is IMHO buggy (and which is, in any case, not in nixpkgs) such as https://git.lix.systems/lix-project/lix/issues/445, we don't think anyone doing anything reasonable actually depends on wrapping overflow. Even for weird use cases such as doing funny bit crimes, it doesn't make sense IMO to have wrapping behaviour, since two's complement arithmetic overflow behaviour is so *aggressively* not what you want for *any* kind of mathematics/algorithms. The Nix language exists for package management, a domain where bit crimes are already only dubiously in scope to begin with, and it makes a lot more sense for that domain for the integers to never lose precision, either by throwing errors if they would, or by being arbitrary-precision. This change will be ported to CppNix as well, to maintain language consistency. Fixes: https://git.lix.systems/lix-project/lix/issues/423 Change-Id: I51f253840c4af2ea5422b8a420aa5fafbf8fae75
2024-07-04distinguish between throws & errors during throwQyriad
Turns errors like this: let throwMsg = a: throw (a + " invalid bar"); in throwMsg "bullshit" error: … from call site at «string»:3:4: 2| throwMsg = a: throw (a + " invalid bar"); 3| in throwMsg "bullshit" | ^ … while calling 'throwMsg' at «string»:2:14: 1| let 2| throwMsg = a: throw (a + " invalid bar"); | ^ 3| in throwMsg "bullshit" … while calling the 'throw' builtin at «string»:2:17: 1| let 2| throwMsg = a: throw (a + " invalid bar"); | ^ 3| in throwMsg "bullshit" error: bullshit invalid bar into errors like this: let throwMsg = a: throw (a + " invalid bar"); in throwMsg "bullshit" error: … from call site at «string»:3:4: 2| throwMsg = a: throw (a + " invalid bar"); 3| in throwMsg "bullshit" | ^ … while calling 'throwMsg' at «string»:2:14: 1| let 2| throwMsg = a: throw (a + " invalid bar"); | ^ 3| in throwMsg "bullshit" … caused by explicit throw at «string»:2:17: 1| let 2| throwMsg = a: throw (a + " invalid bar"); | ^ 3| in throwMsg "bullshit" error: bullshit invalid bar Change-Id: I593688928ece20f97999d1bf03b2b46d9ac338cb
2024-07-04trace when the `foo` part of `foo.bar.baz` errorsQyriad
Turns errors like: let errpkg = throw "invalid foobar"; in errpkg.meta error: … while calling the 'throw' builtin at «string»:2:12: 1| let 2| errpkg = throw "invalid foobar"; | ^ 3| in errpkg.meta error: invalid foobar into errors like: let errpkg = throw "invalid foobar"; in errpkg.meta error: … while evaluating 'errpkg' to select 'meta' on it at «string»:3:4: 2| errpkg = throw "invalid foobar"; 3| in errpkg.meta | ^ … while calling the 'throw' builtin at «string»:2:12: 1| let 2| errpkg = throw "invalid foobar"; | ^ 3| in errpkg.meta error: invalid foobar For the low price of one try/catch, you too can have the incorrect line of code actually show up in the trace! Change-Id: If8d6200ec1567706669d405c34adcd7e2d2cd29d
2024-06-25libexpr: rewrite the parser with pegtl instead of flex/bisoneldritch horrors
this gives about 20% performance improvements on pure parsing. obviously it will be less on full eval, but depending on how much parsing is to be done (e.g. including hackage-packages.nix or not) it's more like 4%-10%. this has been tested (with thousands of core hours of fuzzing) to ensure that the ASTs produced by the new parser are exactly the same as the old one would have produced. error messages will change (sometimes by a lot) and are not yet perfect, but we would rather leave this as is for later. test results for running only the parser (excluding the variable binding code) in a tight loop with inputs and parameters as given are promising: - 40% faster on lix's package.nix at 10000 iterations - 1.3% faster on nixpkgs all-packages.nix at 1000 iterations - equivalent on all of nixpkgs concatenated at 100 iterations (excluding invalid files, each file surrounded with parens) more realistic benchmarks are somewhere in between the extremes, parsing once again getting the largest uplift. other realistic workloads improve by a few percentage points as well, notably system builds are 4% faster. Benchmarks summary (from ./bench/summarize.jq bench/bench-*.json) old/bin/nix --extra-experimental-features 'nix-command flakes' eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix mean: 0.408s ± 0.025s user: 0.355s | system: 0.033s median: 0.389s range: 0.388s ... 0.442s relative: 1 new/bin/nix --extra-experimental-features 'nix-command flakes' eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix mean: 0.332s ± 0.024s user: 0.279s | system: 0.033s median: 0.314s range: 0.313s ... 0.361s relative: 0.814 --- old/bin/nix --extra-experimental-features 'nix-command flakes' eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' mean: 6.133s ± 0.022s user: 5.395s | system: 0.437s median: 6.128s range: 6.099s ... 6.183s relative: 1 new/bin/nix --extra-experimental-features 'nix-command flakes' eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' mean: 5.925s ± 0.025s user: 5.176s | system: 0.456s median: 5.934s range: 5.861s ... 5.943s relative: 0.966 --- GC_INITIAL_HEAP_SIZE=10g old/bin/nix eval --extra-experimental-features 'nix-command flakes' --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' mean: 4.503s ± 0.027s user: 3.731s | system: 0.547s median: 4.499s range: 4.478s ... 4.541s relative: 1 GC_INITIAL_HEAP_SIZE=10g new/bin/nix eval --extra-experimental-features 'nix-command flakes' --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' mean: 4.285s ± 0.031s user: 3.504s | system: 0.571s median: 4.281s range: 4.221s ... 4.328s relative: 0.951 --- old/bin/nix --extra-experimental-features 'nix-command flakes' search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6c6fe19ccb59cac54b5b3f25e160870 hello mean: 16.475s ± 0.07s user: 14.088s | system: 1.572s median: 16.495s range: 16.351s ... 16.536s relative: 1 new/bin/nix --extra-experimental-features 'nix-command flakes' search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6c6fe19ccb59cac54b5b3f25e160870 hello mean: 15.973s ± 0.013s user: 13.558s | system: 1.615s median: 15.973s range: 15.946s ... 15.99s relative: 0.97 --- Change-Id: Ie66ec2d045dec964632c6541e25f8f0797319ee2
2024-06-01chore: rebrand Nix to Lix when it makes senseRaito Bezarius
Here's my guide so far: $ rg '((?!(recursive).*) Nix (?!(daemon|store|expression|Rocks!|Packages|language|derivation|archive|account|user|sandbox|flake).*))' -g '!doc/' --pcre2 All items from this query have been tackled. For the documentation side: that's for https://git.lix.systems/lix-project/lix/issues/162. Additionally, all remaining references to github.com/NixOS/nix which were not relevant were also replaced. Fixes: https://git.lix.systems/lix-project/lix/issues/148. Fixes: https://git.lix.systems/lix-project/lix/issues/162. Change-Id: Ib3451fae5cb8ab8cd9ac9e4e4551284ee6794545 Signed-off-by: Raito Bezarius <raito@lix.systems>
2024-04-04Rename some parse failure tests to `parse-fail-*`Rebecca Turner
These were mistakenly labeled `eval-fail-*`. Note that the `lang.sh` runner passes `parse-fail-*` tests on stdin, so filenames are removed from error messages. Change-Id: I7f3a0d78b6cfa87af29aaa1b7af19d5a57fd4ade
2024-03-18use byte indexed locations for PosIdxeldritch horrors
we now keep not a table of all positions, but a table of all origins and their sizes. position indices are now direct pointers into the virtual concatenation of all parsed contents. this slightly reduces memory usage and time spent in the parser, at the cost of not being able to report positions if the total input size exceeds 4GiB. this limit is not unique to nix though, rustc and clang also limit their input to 4GiB (although at least clang refuses to process inputs that are larger, we will not). this new 4GiB limit probably will not cause any problems for quite a while, all of nixpkgs together is less than 100MiB in size and already needs over 700MiB of memory and multiple seconds just to parse. 4GiB worth of input will easily take multiple minutes and over 30GiB of memory without even evaluating anything. if problems *do* arise we can probably recover the old table-based system by adding some tracking to Pos::Origin (or increasing the size of PosIdx outright), but for time being this looks like more complexity than it's worth. since we now need to read the entire input again to determine the line/column of a position we'll make unsafeGetAttrPos slightly lazy: mostly the set it returns is only used to determine the file of origin of an attribute, not its exact location. the thunks do not add measurable runtime overhead. notably this change is necessary to allow changing the parser since apparently nothing supports nix's very idiosyncratic line ending choice of "anything goes", making it very hard to calculate line/column positions in the parser (while byte offsets are very easy). (cherry picked from commit 5d9fdab3de0ee17c71369ad05806b9ea06dfceda) Change-Id: Ie0b2430cb120c09097afa8c0101884d94f4bbf34
2024-03-18diagnose "unexpected EOF" at EOFeldritch horrors
this needs a string comparison because there seems to be no other way to get that information out of bison. usually the location info is going to be correct (pointing at a bad token), but since EOF isn't a token as such it'll be wrong in that this case. this hasn't shown up much so far because a single line ending *is* a token, so any file formatted in the usual manner (ie, ending in a line ending) would have its EOF position reported correctly. (cherry picked from commit 855fd5a1bb781e4f722c1d757ba43e866d370132) Change-Id: I120c56a962f4286b1ae3b71da7b71ce8ec3e0535
2024-03-18match line endings used by parser and error reportseldritch horrors
the parser treats a plain \r as a newline, error reports do not. this can lead to interesting divergences if anything makes use of this feature, with error reports pointing to wrong locations in the input (or even outside the input altogether). (cherry picked from commit 2be6b143289e5479cc4a2667bb84e879116c2447) Change-Id: Ieb7f7655bac8cb0cf5734c60bd41723388f2973c
2024-03-18report inherit attr errors at the duplicate nameeldritch horrors
previously we reported the error at the beginning of the binding block (for plain inherits) or the beginning of the attr list (for inherit-from), effectively hiding where exactly the error happened. this also carries over to runtime positions of attributes in sets as reported by unsafeGetAttrPos. we're not worried about this changing observable eval behavior because it *is* marked unsafe, and the new behavior is much more useful. (cherry picked from commit 1edd6fada53553b89847ac3981ac28025857ca02) Change-Id: I2f50eb9f3dc3977db4eb3e3da96f1cb37ccd5174
2024-03-18normalize formal order on ExprLambda::showeldritch horrors
we already normalize attr order to lexicographic, doing the same for formals makes sense. doubly so because the order of formals would otherwise depend on the context of the expression, which is not quite as useful as one might expect. (cherry picked from commit 4147ecfb1c51f3fe3b4adcbd4e753fd487dab645) Change-Id: I3fd0dbdef3ac7447a3a03ff20bb514a0d0f23fb1
2024-03-18keep copies of parser inputs that are in-memory onlyeldritch horrors
the parser modifies its inputs, which means that sharing them between the error context reporting system and the parser itself can confuse the reporting system. usually this led to early truncation of error context reports which, while not dangerous, can be quite confusing. (cherry picked from commit d384ecd553aa997270b79ee98d02f7cf7e1849e6) Change-Id: I677646b5675b12b2faa787943646aa36dc6e6ee3
2024-03-16diagnose duplicated attrs at correct patheldritch horrors
diagnose attr duplication at the path the duplication was detected, not at the path the current attribute wanted to place. doing the latter is only correct if a leaf attribute was duplicated, not if an attrpath was set to a non-attrset in one binding and a (potentially implied) attrset in another binding. fixes #124 Change-Id: Ic4aa9cc12a9874d4e7897c6f64408f10aa36fc82
2024-03-14libexpr: fix elided value counting in printereldritch horrors
using the total-attrs-printed and total-list-items-printed counters to calculate how many attrs were elided only works properly if no nesting is involved. once things do nest the global counter can exceed the size of the currently printed object, leading to unsigned wrapping and great overestimation of elided counts. counting locally in addition to global counts fixes this. these are functional tests because creating these objects requires the evaluator to not be a huge amount of code, and we also want defaults to be tested for cli usage. fixes #14 Change-Id: Icb9a0cb21b2f4bacbc5e9dcdd8c0b9055b4088a7
2024-03-10evaluate inherit (from) exprs only once per directiveeldritch horrors
desugaring inherit-from to syntactic duplication of the source expr also duplicates side effects of the source expr (such as trace calls) and expensive computations (such as derivationStrict). (cherry picked from commit cefd0302b55b3360dbca59cfcb4bf6a750d6cdcf) Change-Id: Iff519f991adef2e51683ba2c552d37a3df7a179e
2024-03-10group inherit by source during Expr::showeldritch horrors
for plain inherits this is really just a stylistic choice, but for inherit-from it actually fixes an exponential size increase problem during expr printing (as may happen during assertion failure reporting, on during duplicate attr detection in the parser) (cherry picked from commit ecf8b12d60ad2929f9998666cf0966475b91e291) Change-Id: Ie55f0cb01a37e766414c31f8d40f51c2c7d106b0
2024-03-10use the same bindings print for ExprAttrs and ExprLeteldritch horrors
this also has the effect of sorting let bindings lexicographically rather than by symbol creation order as was previously done, giving a better canonicalization in the process. (cherry picked from commit 6c08fba533ef31cad2bdc03ba72ecf58dc8ee5a0) Change-Id: Ia887f629305645bb8a165fbbc0d32e620912595a
2024-03-10add test for inherit expr printingeldritch horrors
(cherry picked from commit 73065a400d176b21f518c1f4ece90c31318b218d) Change-Id: I9356d8084d241a7904b66554d7c4194f8433edf7
2024-03-10add test for inherit-from semanticseldritch horrors
(cherry picked from commit 8669c02468994887be91072ac58b1ee43380d354) Change-Id: If8513316bf4b4b559c5bb63842c856f016816802
2024-03-09Merge pull request #10066 from 9999years/print-all-frameseldritch horrors
Do not skip any stack frames when `--show-trace` is given (cherry picked from commit 0b47783d0a879875d558f0b56e49584f25ceb2d0) Change-Id: Ia0f18266dbcf97543110110c655c219c7a3e3270
2024-03-09Pretty-print values in the REPLeldritch horrors
Pretty-print values in the REPL by printing each item in a list or attrset on a separate line. When possible, single-item lists and attrsets are printed on one line, as long as they don't contain a nested list, attrset, or thunk. Before: ``` { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } ``` After: ``` { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } ``` (cherry picked from commit c0a15fb7d03dfb8f53bc6726c414bc88aa362592) Change-Id: Ia2b41849165a5ddb63f7a8c272a2476b3e4292df
2024-03-09libexpr: Support structured error classeseldritch horrors
While preparing PRs like #9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`. (cherry picked from commit c6a89c1a1659b31694c0fbcd21d78a6dd521c732) Change-Id: Iced91ba4e00ca9e801518071fb43798936cbd05a
2024-03-09Merge pull request #9754 from 9999years/print-value-when-coercion-failseldritch horrors
Print the value in `error: cannot coerce` messages (cherry picked from commit 5b7bfd2d6b89d7dd5f54c1ca6c8072358d31a84e) === test taken from 6e8d5983143ae576e3f4b1d2954a5267f2943a49; it was added previously (and not backported because its pr was a mostly-revert), but it's useful to have around. Change-Id: Icbd14b55e3610ce7b774667bf14b82e6dc717982
2024-03-09Merge pull request #9753 from 9999years/print-value-on-type-erroreldritch horrors
Print the value in `value is X while a Y is expected` error (cherry picked from commit 5f72a97092da6af28a7d2b2a50d74e9d34fae7e1) Change-Id: Idb4bc903ae59a0f5b6fb3b1da4d47970fe0a6efe
2024-03-09Unify and refactor value printingeldritch horrors
Previously, there were two mostly-identical value printers -- one in `libexpr/eval.cc` (which didn't force values) and one in `libcmd/repl.cc` (which did force values and also printed ANSI color codes). This PR unifies both of these printers into `print.cc` and provides a `PrintOptions` struct for controlling the output, which allows for toggling whether values are forced, whether repeated values are tracked, and whether ANSI color codes are displayed. Additionally, `PrintOptions` allows tuning the maximum number of attributes, list items, and bytes in a string that will be displayed; this makes it ideal for contexts where printing too much output (e.g. all of Nixpkgs) is distracting. (As requested by @roberth in https://github.com/NixOS/nix/pull/9554#issuecomment-1845095735) Please read the tests for example output. Future work: - It would be nice to provide this function as a builtin, perhaps `builtins.toStringDebug` -- a printing function that never fails would be useful when debugging Nix code. - It would be nice to support customizing `PrintOptions` members on the command line, e.g. `--option to-string-max-attrs 1000`. (cherry picked from commit 0fa08b451682fb3311fe58112ff05c4fe5bee3a4, ) === Restore ambiguous value printer for `nix-instantiate` The Nix team has requested that this output format remain unchanged. I've added a warning to the man page explaining that `nix-instantiate --eval` output will not parse correctly in many situations. (cherry picked from commit df84dd4d8dd3fd6381ac2ca3064432ab31a16b79) Change-Id: I7cca6b4b53cd0642f2d49af657d5676a8554c9f8
2024-03-07Merge pull request #9985 from alois31/symlink-resolutioneldritch horrors
Restore `builtins.pathExists` behavior on broken symlinks (cherry picked from commit d53c8901ef7f2033855dd99063522e3d56a19dab) === note that this variant differs markedly from the source commit because we haven't endured quite as much lazy trees. Change-Id: I0facf282f21fe0db4134be5c65a8368c1b3a06fc
2024-03-04Merge pull request #9861 from 9999years/colored-diff-in-lang-testseldritch horrors
Color `diff` output in `tests/functional/lang` tests (cherry picked from commit 1dc55c0f2f034bce6e3de4a5cda96d686b10a7f8) Change-Id: Ie9b3fc3446bd3caa0fd8885de88639516a2ff862
2024-03-04Merge pull request #9785 from hercules-ci/test-substring-negativeeldritch horrors
tests/functional/lang: Test substring with negative length (cherry picked from commit 86156d05dd33f856d8804f89669a7fe9b81f1a0d) Change-Id: I2e2086027a43f8111ba5068ac16590eaa0b798d4
2024-03-04Merge pull request #9747 from awakesecurity/mz/fix-quadratic-splitStringeldritch horrors
Fix performance of builtins.substring for empty substrings (cherry picked from commit b2deff1947c2fe57fdbf1a472eb9003eb407f8d3) Change-Id: I4ddfc8d26a4781c9520fff9807849a073ee7bed8
2024-03-04Merge pull request #9617 from 9999years/stack-overflow-segfaulteldritch horrors
Fix segfault on infinite recursion in some cases (cherry picked from commit bf1b294bd81ca76c5ec9fe3ecd52196bf52a8300) Change-Id: Id137541426ec8536567835953fccf986a3aebf16
2024-03-04Merge pull request #9619 from 9999years/remove-blank-lines-in-errorseldritch horrors
Remove some blank lines from stack traces (cherry picked from commit cea83544362bd6426e9bc0b7dd0d611c19b0e3fd) Change-Id: Ic1af8b09e9994d3c69fd3b37ae47a4bb786a15a1
2024-03-04Merge pull request #9555 from 9999years/positions-in-errorseldritch horrors
Pass positions when evaluating (cherry picked from commit c8458bd731eb1c74159bebe459ea00165e056b65) Change-Id: I1b4a5d58973be6264ffdb23b4492da200fdb71be
2024-03-04Merge pull request #9216 from obsidiansystems/addDrvOutputDependencies-preeldritch horrors
Add `builtins.addDrvOutputDependencies` (cherry picked from commit a58d7f143ec995a45745c2176bfebcc3e011db58) Change-Id: Ia5a1790bf29dfaf29287cc35cdae6b6d650e7a83
2024-03-04Merge pull request #9168 from obsidiansystems/fix-lang-tests-read-onlyeldritch horrors
Fix language tests a bit (cherry picked from commit e92cac789fc84b116a03db04a5f7de8df48e34cd) Change-Id: I527e94c5af0921ff2559ce5a4ac7635be791c22e
2024-03-04Merge pull request #8905 from hercules-ci/no-unknown-locationeldritch horrors
Don't print unknown locations unless requested for dev purposes (cherry picked from commit 3dd4475826dff8052fef42d4600b61e6b91950ac) Change-Id: I04a91277d1d9d09f5c1bf4a28fc99f0702b161e5
2024-01-21Fix symlink handlingEelco Dolstra
This restores the symlink handling behaviour prior to 94812cca98fbb157e5f64a15a85a2b852d289feb. Fixes #9298. (cherry picked from commit 31ebc6028b3682969d86a7b39ae87131c41cc604)
2023-12-01Put functional tests in `tests/functional`John Ericson
I think it is bad for these reasons when `tests/` contains a mix of functional and integration tests - Concepts is harder to understand, the documentation makes a good unit vs functional vs integration distinction, but when the integration tests are just two subdirs within `tests/` this is not clear. - Source filtering in the `flake.nix` is more complex. We need to filter out some of the dirs from `tests/`, rather than simply pick the dirs we want and take all of them. This is a good sign the structure of what we are trying to do is not matching the structure of the files. With this change we have a clean: ```shell-session $ git show 'HEAD:tests' tree HEAD:tests functional/ installer/ nixos/ ``` (cherry picked from commit 68c81c737571794f7246db53fb4774e94fcf4b7e)