Commit Graph
3 Commits
Author SHA1 Message Date
dualfroz b0f3a8b909 fix(xml): panic when encoding a sequence tagged as a map
The pre-pass that emits processing instructions first walks Content in
key/value pairs, which is only valid for a mapping, but it gated on
node.Tag instead of node.Kind. A sequence tagged !!map can have an odd
Content length, so Content[i+1] ran off the end:

    printf '!!map [cat, dog, fish]\n' | yq -o=xml
    panic: runtime error: index out of range [3] with length 3

That pre-pass runs before the switch on node.Kind, which would otherwise
have returned the usual 'cannot encode ... to XML' error.

The same check also skipped well formed mappings that carry a custom
tag, so their processing instructions were dropped: encodeTopLevelMap
then skipped the key as already processed and it disappeared from the
output altogether.

Gate the pre-pass on Kind, as the rest of the file already does in the
switch in Encode, in doEncode and in encodeMap.
2026-09-03 14:32:13 +02:00
dualfroz 472a5336be fix: sort no longer panics on a value tagged as a number that is not one
sortableNodeArray.compare called panic(err) when parseInt64 or ParseFloat
failed, so a scalar tagged !!int or !!float whose value is not a number
crashed yq with a Go stack trace. An explicit tag in the input document is
enough to trigger it, no unusual expression needed.

Log a warning and compare the raw strings instead, matching the timestamp
branch a few lines above in the same function and the plain string fallback
the function already ends with. Values that do parse still compare
numerically.
2026-09-03 14:15:29 +02:00
dualfroz 699d0e35c0 fix(equals): compare integers by value, not by raw text
The == and != operators matched the raw text of two scalars, so the same
integer written in a different base never matched: `0x10 == 16`,
`0o644 == 420` and `1_000 == 1000` were all false.

This contradicted yq's own comparison operators, which parse those
formats and agree the values are equal - for `0o644`, both `> 419` and
`< 421` are true, yet `== 420` was false. It also contradicted the
documented "Match number" behaviour of `==`.

Give ==/!= the same !!int/!!int branch the comparison operators already
have: parse both sides with the existing parseInt64 helper and compare
the resulting int64s. If either side does not fit in an int64, fall back
to the previous raw match rather than raising a new error. String
globbing, floats and null handling are unchanged.

Fixes #1977
2026-09-03 13:29:22 +02:00