Skip to content

libnvpair_json tickles incompatibilities between JSON parsers by representing 64 bit numbers as numbers #11610

Open
@grahamc

Description

@grahamc

System information

Type Version/Name
Distribution Name NixOS
Distribution Version 20.09
Linux Kernel 5.10.15
Architecture x86_64
ZFS Version 2.0.2-1
SPL Version 2.0.2-1

(but this is all fairly irrelevant)

Describe the problem you're observing

The libnvpair_json library code uses numbers for large numbers:

case DATA_TYPE_INT64: {
FPRINTF(fp, "%lld",
(long long)fnvpair_value_int64(curr));
break;
}
case DATA_TYPE_UINT64: {
FPRINTF(fp, "%llu",
(unsigned long long)fnvpair_value_uint64(curr));
break;
}
case DATA_TYPE_HRTIME: {
hrtime_t val;
VERIFY0(nvpair_value_hrtime(curr, &val));
FPRINTF(fp, "%llu", (unsigned long long)val);
break;
}
case DATA_TYPE_DOUBLE: {
double val;
VERIFY0(nvpair_value_double(curr, &val));
FPRINTF(fp, "%f", val);
break;
}

However, JavaScript represents all numbers as floating point, with a 53 bit mantissa. This means that integers in JSON which are larger than 2^53 are truncated.Some non-JavaScript JSON parsers try to carefully match the semantics of JavaScript and can introduce these mysteries.

See: https://rachelbythebay.com/w/2021/02/03/bits/

Describe how to reproduce the problem

  1. Create a ZFS Channel Program which emits some large numbers as json
  2. Consume that JSON via various parsers

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions