Lix JSON parser silently accepts duplicate object keys #1162

Open
opened 2026-03-20 00:01:03 +00:00 by sky1e · 1 comment
Member

Describe the bug

Lix's JSON parser used by builtins.fromJSON silently accepts duplicate object keys, discarding all values but the last.

Steps To Reproduce

nix eval --expr 'builtins.fromJSON '"''"'{"a":"a","a":"b"}'"''"
> { a = "b" }

Expected behavior

Such unusual JSON input should be rejected, or if not, the current behavior should be at least tested for.

nix --version output

nix (Lix, like Nix) 2.94.0
System type: x86_64-linux
Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux
Features: gc, signed-caches
System configuration file: /etc/nix/nix.conf
User configuration files: /home/skye/.config/nix/nix.conf:/nix/store/0q6ydqfjgwhlsczwi5jk4ds1dpxdnrns-plasma-workspace-6.6.2/etc/xdg/nix/nix.conf:/nix/store/1r1bfsknakc5kfz0gmf0i3h9jqlqqcnn-kglobalacceld-6.6.2/etc/xdg/nix/nix.conf:/nix/store/qrw4yjb7king22w52ivrjaa5d1vkx9zc-baloo-6.24.0/etc/xdg/nix/nix.conf:/home/skye/.config/kdedefaults/nix/nix.conf:/home/skye/.config/kdedefaults/nix/nix.conf:/etc/xdg/nix/nix.conf:/home/skye/.local/share/flatpak/exports/etc/xdg/nix/nix.conf:/var/lib/flatpak/exports/etc/xdg/nix/nix.conf:/home/skye/.nix-profile/etc/xdg/nix/nix.conf:/nix/profile/etc/xdg/nix/nix.conf:/home/skye/.local/state/nix/profile/etc/xdg/nix/nix.conf:/etc/profiles/per-user/skye/etc/xdg/nix/nix.conf:/nix/var/nix/profiles/default/etc/xdg/nix/nix.conf:/run/current-system/sw/etc/xdg/nix/nix.conf
Store directory: /nix/store
State directory: /nix/var/nix
Data directory: /nix/store/0zqbw17irvj0c71wn6cjbmcg2v04gzvd-lix-2.94.0/share

Additional context

The existing behavior is defined by JSONObjectState in lix/libexpr/json-to-value.cc

class JSONObjectState : public JSONState {
using JSONState::JSONState;
GcMap<Symbol, Value> attrs;
Symbol _key;
std::unique_ptr<JSONState> resolve(EvalState & state) override
{
auto attrs2 = state.ctx.buildBindings(attrs.size());
for (auto & i : attrs)
attrs2.insert(i.first, i.second);
parent->value() = {NewValueAs::attrs, attrs2.alreadySorted()};
return std::move(parent);
}
void add() override
{
attrs.insert_or_assign(_key, value());
v = nullptr;
}
public:
void key(string_t & name, EvalState & state)
{
_key = state.ctx.symbols.create(name);
}
};

## Describe the bug Lix's JSON parser used by `builtins.fromJSON` silently accepts duplicate object keys, discarding all values but the last. ## Steps To Reproduce ``` nix eval --expr 'builtins.fromJSON '"''"'{"a":"a","a":"b"}'"''" > { a = "b" } ``` ## Expected behavior Such unusual JSON input should be rejected, or if not, the current behavior should be at least tested for. ## `nix --version` output ``` nix (Lix, like Nix) 2.94.0 System type: x86_64-linux Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux Features: gc, signed-caches System configuration file: /etc/nix/nix.conf User configuration files: /home/skye/.config/nix/nix.conf:/nix/store/0q6ydqfjgwhlsczwi5jk4ds1dpxdnrns-plasma-workspace-6.6.2/etc/xdg/nix/nix.conf:/nix/store/1r1bfsknakc5kfz0gmf0i3h9jqlqqcnn-kglobalacceld-6.6.2/etc/xdg/nix/nix.conf:/nix/store/qrw4yjb7king22w52ivrjaa5d1vkx9zc-baloo-6.24.0/etc/xdg/nix/nix.conf:/home/skye/.config/kdedefaults/nix/nix.conf:/home/skye/.config/kdedefaults/nix/nix.conf:/etc/xdg/nix/nix.conf:/home/skye/.local/share/flatpak/exports/etc/xdg/nix/nix.conf:/var/lib/flatpak/exports/etc/xdg/nix/nix.conf:/home/skye/.nix-profile/etc/xdg/nix/nix.conf:/nix/profile/etc/xdg/nix/nix.conf:/home/skye/.local/state/nix/profile/etc/xdg/nix/nix.conf:/etc/profiles/per-user/skye/etc/xdg/nix/nix.conf:/nix/var/nix/profiles/default/etc/xdg/nix/nix.conf:/run/current-system/sw/etc/xdg/nix/nix.conf Store directory: /nix/store State directory: /nix/var/nix Data directory: /nix/store/0zqbw17irvj0c71wn6cjbmcg2v04gzvd-lix-2.94.0/share ``` ## Additional context The existing behavior is defined by `JSONObjectState` in `lix/libexpr/json-to-value.cc` https://git.lix.systems/lix-project/lix/src/commit/774f95759908891d9f9bcd2dd3271f5c148359d7/lix/libexpr/json-to-value.cc#L37-L59
Author
Member

Since I'm already in the weeds in the JSON parser I'm happy to drive a fix, but that first requires determining how this will be fixed. This would be a breaking change. Would we want to warn first before making it an error? Would we need to add a flag to re-enable old behavior?

Since I'm already in the weeds in the JSON parser I'm happy to drive a fix, but that first requires determining how this will be fixed. This would be a breaking change. Would we want to warn first before making it an error? Would we need to add a flag to re-enable old behavior?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lix-project/lix#1162
No description provided.