Bug 1614569

Summary: Jansson can not always parse QEMU's JSON
Product: [Community] Virtualization Tools Reporter: Michael Chapman <redhat-bugzilla>
Component: libvirtAssignee: Libvirt Maintainers <libvirt-maint>
Status: CLOSED NEXTRELEASE QA Contact:
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: unspecifiedCC: berrange, jtomko, libvirt-maint, mikhail.v.gavrilov, rjones, tburke
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-08-13 13:58:35 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1496189    

Description Michael Chapman 2018-08-10 00:00:09 UTC
Jansson uses `strtoll` to parse integers, and it explicitly checks for integer overflow [1]. This can only parse signed long longs, but QEMU sometimes produces JSON containing 2^64-1.

    # virsh start example --paused
    Domain example started

    # virsh domstats example
    Domain: 'example'
      [... some stats, but no error ...]

    # virsh resume example
    error: Failed to resume domain example
    error: internal error: failed to parse JSON 1:59: too big integer near '18446744073709551615'

This wedges the monitor object completely, and no further operations on the VM are possible.

I'm not really sure of the best way of solving this. A standards-compliant JSON implementation need not support integers outside of the range of JavaScript's Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER [2], but QEMU is unfortunately relying on clients supporting full unsigned 64-bit integers.

(Although YAJL has the same kind of validation as Jansson, libvirt was avoiding the problem since it would register its own callback to parse numbers.)

[1] https://jansson.readthedocs.io/en/latest/conformance.html#numbers
[2] http://www.ecma-international.org/ecma-262/6.0/index.html#sec-number.max_safe_integer

Comment 1 Daniel Berrangé 2018-08-10 09:41:58 UTC
Looks like we are pretty doomed - Jansson devs have refused to support unsigned 64-bit ints  https://github.com/akheron/jansson/issues/154

AFAICT, there's no way to get the original value as a string in jansson either - it will always parse it :-(

Comment 2 Ján Tomko 2018-08-10 11:17:18 UTC
Sigh,

even if we extend the range and say goodbye to precision by using JSON_DECODE_INT_AS_REAL, it will not overflow to -1 which QEMU expects us to do here.

I believe this is solved by my earlier series 'Revert the switch to Jansson':
https://www.redhat.com/archives/libvir-list/2018-July/msg02106.html

Comment 3 Daniel Berrangé 2018-08-10 11:23:54 UTC
Yeah, I've looked at the source and there is no "get out of jail free" option here - the parser has no way to expose the number as a string like yajl did. 

This looks like a terminal problem with jansson with revert being only option :-(

c-json doesn't look any better in this respect either, also using strtoll

Comment 4 Richard W.M. Jones 2018-08-10 12:41:07 UTC
I pointed out years and years ago that JSON integers are fundamentally
undefined:

https://lists.gnu.org/archive/html/qemu-devel/2011-05/msg02437.html

Comment 5 Ján Tomko 2018-08-13 11:56:40 UTC
Revert of the Jansson switch:
https://www.redhat.com/archives/libvir-list/2018-August/msg00633.html

Comment 6 Ján Tomko 2018-08-13 13:58:35 UTC
Pushed as of:
commit 86db0db979c39df278f03dbf3b4239c873ddb637
Author:     Ján Tomko <jtomko>
CommitDate: 2018-08-13 15:50:01 +0200

    Revert "build: add --with-jansson"

git describe: v4.6.0-128-g86db0db979