Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve custom/complex argument JSON parsing for chip-tool. #19530

Merged
merged 1 commit into from
Jun 14, 2022

Conversation

bzbarsky-apple
Copy link
Contributor

@bzbarsky-apple bzbarsky-apple commented Jun 13, 2022

Specific changes:

  1. Use CharReaderBuilder/CharReader, because that allows us to set 'failIfExtra'
    to true, so we fail out on trailing garbage.
  2. Since now we can, set 'allowSingleQuotes' to true, so people can use single
    quotes in their JSON if that's more convenient.
  3. Add checking for duplicated keys by setting rejectDupKeys to true.
  4. For complex arguments, enforce that the value is in fact an array or object,
    not a primitive value.
  5. Factour out the parsing logic from ComplexArgument so we can use it in
    CustomArgument too.
  6. Make CustomArgument fail out on JSON parse errors instead of silently doing
    unexpected things.
  7. For CustomArgument, detect an argument starting with one of our type prefixes
    ("hex:", "i:", "u:", "f:", "d:") and if so just treat it as a string value
    instead of trying to do a full JSON parse (which would fail anyway).
  8. For CustomArgument, detect an argument starting with "0x" and treat it as a
    string starting "u:0x", so it will be parsed as a hex number instead of just
    failing to parse.

This leads to the following behavior:

./chip-tool any write-by-id 0x130AFC01 0x130A0001 123 17 1

Before: sends 123 as signed int.
After: same.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 0x123 17 1

Before: sends 0.
After: sends 291 as unsigned int.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 u:123 17 1

Before: sends null.
After: sends 123 as unsigned int.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 hex:121314 17 1

Before: sends null.
After: sends byte string with bytes 0x12, 0x13, 0x14.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 "[1, 2, 3], [4, 5, 6]" 17 1

Before: sends list [1, 2, 3].
After: errors out on trailing garbage.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 "[1 2, 3]" 17 1

Before: sends list [1].
After: errors out with "Missing ',' or ']' in array declaration".

./chip-tool accesscontrol write acl '[{"privilege": 5, "authMode": 2, "subjects": [112233], "targets": [{"cluster": null, "endpoint": null, "deviceType": 0x100}]}]' 17 0

Before: Errors out on the invalid hex number not in quotes, shows the error location.
After: same.

./chip-tool accesscontrol write acl '[{"privilege": 5, "authMode": 2, "subjects": [112233], "targets": []}], [{"targets": [{"cluster": null, "endpoint": null, "deviceType": 0x100}]}]' 17 0

Before: sends the first array and ignores the second one.
After: errors out on trailing garbage.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 '{"1": 0x100 }' 17 1

Before: Sends {"1": 0}
After: Parse error on invalid hex.

./chip-tool any write-by-id 0x130AFC01 0x130A0001 '{"1": "u:0x100" }' 17 1

Before: sends {"1": 256}
After: same.

Fixes #19529

Problem

Sending garbage instead of failing out on invalid JSON for custom arguments. Not reporting trailing garbage for complex arguments.

Change overview

See above.

Testing

See above for list of things tested.

Specific changes:

1) Use CharReaderBuilder/CharReader, because that allows us to set 'failIfExtra'
   to true, so we fail out on trailing garbage.
2) Since now we can, set 'allowSingleQuotes' to true, so people can use single
   quotes in their JSON if that's more convenient.
3) Add checking for duplicated keys by setting rejectDupKeys to true.
4) For complex arguments, enforce that the value is in fact an array or object,
   not a primitive value.
5) Factour out the parsing logic from ComplexArgument so we can use it in
   CustomArgument too.
6) Make CustomArgument fail out on JSON parse errors instead of silently doing
   unexpected things.
7) For CustomArgument, detect an argument starting with one of our type prefixes
   ("hex:", "i:", "u:", "f:", "d:") and if so just treat it as a string value
   instead of trying to do a full JSON parse (which would fail anyway).
8) For CustomArgument, detect an argument starting with "0x" and treat it as a
   string starting "u:0x", so it will be parsed as a hex number instead of just
   failing to parse.

This leads to the following behavior:

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 123 17 1

Before: sends 123 as signed int.
After: same.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 0x123 17 1

Before: sends 0.
After: sends 291 as unsigned int.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 u:123 17 1

Before: sends null.
After: sends 123 as unsigned int.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 hex:121314 17 1

Before: sends null.
After: sends byte string with bytes 0x12, 0x13, 0x14.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 "[1, 2, 3], [4, 5, 6]" 17 1

Before: sends list [1, 2, 3].
After: errors out on trailing garbage.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 "[1 2, 3]" 17 1

Before: sends list [1].
After: errors out with "Missing ',' or ']' in array declaration".

    ./chip-tool accesscontrol write acl '[{"privilege": 5, "authMode": 2, "subjects": [112233], "targets": [{"cluster": null, "endpoint": null, "deviceType": 0x100}]}]' 17 0

Before: Errors out on the invalid hex number not in quotes, shows the error location.
After: same.

    ./chip-tool accesscontrol write acl '[{"privilege": 5, "authMode": 2, "subjects": [112233], "targets": []}], [{"targets": [{"cluster": null, "endpoint": null, "deviceType": 0x100}]}]' 17 0

Before: sends the first array and ignores the second one.
After: errors out on trailing garbage.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 '{"1": 0x100 }' 17 1

Before: Sends {"1": 0}
After: Parse error on invalid hex.

    ./chip-tool any write-by-id 0x130AFC01 0x130A0001 '{"1": "u:0x100" }' 17 1

Before: sends {"1": 256}
After: same.

Fixes project-chip#19529
@github-actions
Copy link

github-actions bot commented Jun 13, 2022

PR #19530: Size comparison from 0e9b2cc to c77c66e

Increases above 0.2%:

platform target config section 0e9b2cc c77c66e change % change
linux chip-tool debug .rodata 506805 508053 1248 0.2
chip-tool-no-interactive-ipv6only arm64 .got 15056 15104 48 0.3
.rodata 468788 470484 1696 0.4
Increases (2 builds for linux)
platform target config section 0e9b2cc c77c66e change % change
linux chip-tool debug (read/write) 623496 623688 192 0.0
.data.rel.ro 590696 590856 160 0.0
.got 5000 5008 8 0.2
.rodata 506805 508053 1248 0.2
chip-tool-no-interactive-ipv6only arm64 (read only) 9563860 9564980 1120 0.0
(read/write) 689841 690049 208 0.0
.data.rel.ro 626128 626288 160 0.0
.got 15056 15104 48 0.3
.rodata 468788 470484 1696 0.4
Decreases (3 builds for cyw30739, linux)
platform target config section 0e9b2cc c77c66e change % change
cyw30739 ota-requestor-no-progress-logging cyw930739m2evb_01 (read/write) 611382 611374 -8 -0.0
.app_xip_area 470808 470800 -8 -0.0
linux chip-tool debug (read only) 9815973 9802661 -13312 -0.1
.text 7868549 7853669 -14880 -0.2
chip-tool-no-interactive-ipv6only arm64 .text 7518980 7517892 -1088 -0.0
Full report (34 builds for cc13x2_26x2, cyw30739, k32w, linux, mbed, nrfconnect, p6, telink)
platform target config section 0e9b2cc c77c66e change % change
cc13x2_26x2 all-clusters-app LP_CC2652R7 (read only) 658295 658295 0 0.0
(read/write) 192592 192592 0 0.0
.bss 73780 73780 0 0.0
.data 3416 3416 0 0.0
.rodata 87023 87023 0 0.0
.text 570960 570960 0 0.0
all-clusters-minimal-app LP_CC2652R7 (read only) 644835 644835 0 0.0
(read/write) 157276 157276 0 0.0
.bss 73004 73004 0 0.0
.data 3356 3356 0 0.0
.rodata 90035 90035 0 0.0
.text 554480 554480 0 0.0
lock-ftd LP_CC2652R7 (read only) 687707 687707 0 0.0
(read/write) 154252 154252 0 0.0
.bss 71740 71740 0 0.0
.data 3280 3280 0 0.0
.rodata 98859 98859 0 0.0
.text 588364 588364 0 0.0
lock-mtd LP_CC2652R7 (read only) 637115 637115 0 0.0
(read/write) 144872 144872 0 0.0
.bss 67476 67476 0 0.0
.data 3280 3280 0 0.0
.rodata 98739 98739 0 0.0
.text 537884 537884 0 0.0
pump-app LP_CC2652R7 (read only) 669083 669083 0 0.0
(read/write) 173788 173788 0 0.0
.bss 71884 71884 0 0.0
.data 3316 3316 0 0.0
.rodata 86979 86979 0 0.0
.text 581620 581620 0 0.0
pump-controller-app LP_CC2652R7 (read only) 659655 659655 0 0.0
(read/write) 183320 183320 0 0.0
.bss 71988 71988 0 0.0
.data 3276 3276 0 0.0
.rodata 84879 84879 0 0.0
.text 574292 574292 0 0.0
shell LP_CC2652R7 (read only) 688446 688446 0 0.0
(read/write) 157936 157936 0 0.0
.bss 76076 76076 0 0.0
.data 3420 3420 0 0.0
.rodata 110094 110094 0 0.0
.text 578040 578040 0 0.0
cyw30739 light cyw930739m2evb_01 (read/write) 606562 606562 0 0.0
.app_xip_area 465060 465060 0 0.0
.bss 84432 84432 0 0.0
.data 756 756 0 0.0
.rodata 0 0 0 0.0
.text 112 112 0 0.0
lock cyw930739m2evb_01 (read/write) 603678 603678 0 0.0
.app_xip_area 462032 462032 0 0.0
.bss 84608 84608 0 0.0
.data 724 724 0 0.0
.rodata 0 0 0 0.0
.text 112 112 0 0.0
ota-requestor-no-progress-logging cyw930739m2evb_01 (read/write) 611382 611374 -8 -0.0
.app_xip_area 470808 470800 -8 -0.0
.bss 83616 83616 0 0.0
.data 644 644 0 0.0
.rodata 0 0 0 0.0
.text 112 112 0 0.0
k32w light k32w061+release (read/write) 657248 657248 0 0.0
.bss 69748 69748 0 0.0
.data 2028 2028 0 0.0
.text 579672 579672 0 0.0
lock k32w061+release (read/write) 718860 718860 0 0.0
.bss 70180 70180 0 0.0
.data 2000 2000 0 0.0
.text 640880 640880 0 0.0
linux all-clusters-app debug (read only) 2923761 2923761 0 0.0
(read/write) 188528 188528 0 0.0
.bss 95776 95776 0 0.0
.data 2048 2048 0 0.0
.data.rel.ro 84488 84488 0 0.0
.dynamic 608 608 0 0.0
.got 4544 4544 0 0.0
.init 27 27 0 0.0
.init_array 1032 1032 0 0.0
.rodata 258205 258205 0 0.0
.text 2489906 2489906 0 0.0
all-clusters-minimal-app debug (read only) 2769193 2769193 0 0.0
(read/write) 179888 179888 0 0.0
.bss 94944 94944 0 0.0
.data 1920 1920 0 0.0
.data.rel.ro 76872 76872 0 0.0
.dynamic 608 608 0 0.0
.got 4496 4496 0 0.0
.init 27 27 0 0.0
.init_array 1032 1032 0 0.0
.rodata 258621 258621 0 0.0
.text 2337458 2337458 0 0.0
bridge-app debug+rpc (read only) 2247553 2247553 0 0.0
(read/write) 158752 158752 0 0.0
.bss 82976 82976 0 0.0
.data 3760 3760 0 0.0
.data.rel.ro 66232 66232 0 0.0
.dynamic 608 608 0 0.0
.got 4400 4400 0 0.0
.init 27 27 0 0.0
.init_array 728 728 0 0.0
.rodata 191040 191040 0 0.0
.text 1896530 1896530 0 0.0
chip-tool debug (read only) 9815973 9802661 -13312 -0.1
(read/write) 623496 623688 192 0.0
.bss 25440 25440 0 0.0
.data 1088 1088 0 0.0
.data.rel.ro 590696 590856 160 0.0
.dynamic 624 624 0 0.0
.got 5000 5008 8 0.2
.init 27 27 0 0.0
.init_array 640 640 0 0.0
.rodata 506805 508053 1248 0.2
.text 7868549 7853669 -14880 -0.2
chip-tool-no-interactive-ipv6only arm64 (read only) 9563860 9564980 1120 0.0
(read/write) 689841 690049 208 0.0
.bss 43697 43697 0 0.0
.data 1152 1152 0 0.0
.data.rel.ro 626128 626288 160 0.0
.dynamic 528 528 0 0.0
.got 15056 15104 48 0.3
.init 24 24 0 0.0
.init_array 192 192 0 0.0
.rodata 468788 470484 1696 0.4
.text 7518980 7517892 -1088 -0.0
lighting-app debug+rpc (read only) 2497465 2497465 0 0.0
(read/write) 163416 163416 0 0.0
.bss 84288 84288 0 0.0
.data 2064 2064 0 0.0
.data.rel.ro 71176 71176 0 0.0
.dynamic 608 608 0 0.0
.got 4432 4432 0 0.0
.init 27 27 0 0.0
.init_array 816 816 0 0.0
.rodata 207144 207144 0 0.0
.text 2122130 2122130 0 0.0
lock-app debug (read only) 2443465 2443465 0 0.0
(read/write) 158488 158488 0 0.0
.bss 82944 82944 0 0.0
.data 1552 1552 0 0.0
.data.rel.ro 68120 68120 0 0.0
.dynamic 608 608 0 0.0
.got 4432 4432 0 0.0
.init 27 27 0 0.0
.init_array 784 784 0 0.0
.rodata 221192 221192 0 0.0
.text 2059074 2059074 0 0.0
ota-provider-app debug (read only) 2281729 2281729 0 0.0
(read/write) 152688 152688 0 0.0
.bss 82624 82624 0 0.0
.data 1784 1784 0 0.0
.data.rel.ro 62456 62456 0 0.0
.dynamic 608 608 0 0.0
.got 4496 4496 0 0.0
.init 27 27 0 0.0
.init_array 680 680 0 0.0
.rodata 197336 197336 0 0.0
.text 1923202 1923202 0 0.0
ota-requestor-app debug (read only) 2329289 2329289 0 0.0
(read/write) 155504 155504 0 0.0
.bss 83328 83328 0 0.0
.data 1976 1976 0 0.0
.data.rel.ro 64392 64392 0 0.0
.dynamic 608 608 0 0.0
.got 4456 4456 0 0.0
.init 27 27 0 0.0
.init_array 712 712 0 0.0
.rodata 199520 199520 0 0.0
.text 1964738 1964738 0 0.0
shell debug (read only) 2604841 2604841 0 0.0
(read/write) 219384 219384 0 0.0
.bss 134568 134568 0 0.0
.data 1392 1392 0 0.0
.data.rel.ro 77672 77672 0 0.0
.dynamic 608 608 0 0.0
.got 4176 4176 0 0.0
.init 27 27 0 0.0
.init_array 936 936 0 0.0
.rodata 229778 229778 0 0.0
.text 2215746 2215746 0 0.0
thermostat-no-ble arm64 (read only) 2557916 2557916 0 0.0
(read/write) 191409 191409 0 0.0
.bss 99377 99377 0 0.0
.data 1560 1560 0 0.0
.data.rel.ro 82376 82376 0 0.0
.dynamic 528 528 0 0.0
.got 5080 5080 0 0.0
.init 24 24 0 0.0
.init_array 400 400 0 0.0
.rodata 161332 161332 0 0.0
.text 2158912 2158912 0 0.0
tv-app debug (read only) 3050873 3050873 0 0.0
(read/write) 289864 289864 0 0.0
.bss 200200 200200 0 0.0
.data 4688 4688 0 0.0
.data.rel.ro 78528 78528 0 0.0
.dynamic 608 608 0 0.0
.got 4848 4848 0 0.0
.init 27 27 0 0.0
.init_array 952 952 0 0.0
.rodata 242720 242720 0 0.0
.text 2622370 2622370 0 0.0
tv-casting-app debug (read only) 5349977 5349977 0 0.0
(read/write) 232312 232312 0 0.0
.bss 88072 88072 0 0.0
.data 2480 2480 0 0.0
.data.rel.ro 135528 135528 0 0.0
.dynamic 608 608 0 0.0
.got 4712 4712 0 0.0
.init 27 27 0 0.0
.init_array 872 872 0 0.0
.rodata 342368 342368 0 0.0
.text 4656338 4656338 0 0.0
mbed lock-app CY8CPROTO_062_4343W+release (read only) 6224 6224 0 0.0
(read/write) 2432808 2432808 0 0.0
.bss 208988 208988 0 0.0
.data 5888 5888 0 0.0
.text 1395452 1395452 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 (read/write) 1198315 1198315 0 0.0
bss 141617 141617 0 0.0
rodata 156100 156100 0 0.0
text 821652 821652 0 0.0
all-clusters-minimal-app nrf52840dk_nrf52840 (read/write) 1143531 1143531 0 0.0
bss 140808 140808 0 0.0
rodata 131828 131828 0 0.0
text 791972 791972 0 0.0
p6 all-clusters-app default (read/write) 2551672 2551672 0 0.0
.bss 143408 143408 0 0.0
.data 2832 2832 0 0.0
.text 1509936 1509936 0 0.0
all-clusters-minimal-app default (read/write) 2494128 2494128 0 0.0
.bss 142624 142624 0 0.0
.data 2776 2776 0 0.0
.text 1452392 1452392 0 0.0
light-app default (read/write) 2425560 2425560 0 0.0
.bss 135736 135736 0 0.0
.data 2624 2624 0 0.0
.text 1383824 1383824 0 0.0
lock-app default (read/write) 2445968 2445968 0 0.0
.bss 135560 135560 0 0.0
.data 2600 2600 0 0.0
.text 1404232 1404232 0 0.0
telink light-switch-app tlsr9518adk80d (read/write) 786724 786724 0 0.0
bss 70876 70876 0 0.0
noinit 40416 40416 0 0.0
text 556634 556634 0 0.0
lighting-app tlsr9518adk80d (read/write) 806704 806704 0 0.0
bss 71128 71128 0 0.0
noinit 40416 40416 0 0.0
text 573328 573328 0 0.0

Copy link
Contributor

@krypton36 krypton36 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great change!

@andy31415 andy31415 merged commit b9e1102 into project-chip:master Jun 14, 2022
@bzbarsky-apple bzbarsky-apple deleted the better-json-parsing branch June 14, 2022 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

chip-tool: do not enforce triple quoting of custom arguments
4 participants