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

yaml_test: adapt around undefined behavior in float64->int64 casting #42

Merged

Conversation

neolit123
Copy link
Member

@neolit123 neolit123 commented Nov 12, 2020

In TestJSONObjectToYAMLObject the "uint64 big" case accepts a float64
of size 2^63. The value is passed to jsonToYAMLValue() and the
float64 branch of the switch is entered. For values that do not
fit int64 the first cast to int64() is undefined behavior
in most languages and apparently in Golang:
http://c0x.coding-guidelines.com/6.3.1.4.pdf
(link for the C standard)

This means the value of int64(float64(2^63)) can end up as either
-9223372036854775808 or 9223372036854775807.
From experimentation, it appears compiler optimization
determines the result.

The value is then casted back to float64 and matched against
the original float64, which may or may not pass. Depending of FPU
rounding mode for IEEE754-Doubles any input above 9223372036854775296
may get casted to 9223372036854775808.0.

Adapt the unit test for "uint64 big" to not feed a big float64 and enter
the problem cases. Instead pass the nearest rounded value of 2^63
as a uint64 and expect to receive the same result:
bigUint64 = ((uint64(1) << 63) + 500) / 1000 * 1000

the observed undefined behavior seems to trip tests on non-AMD64:
fixes #34

In TestJSONObjectToYAMLObject the "uint64 big" case accepts a float64
of size 2^63. The value is passed to jsonToYAMLValue() and the
float64 branch of the switch is entered. For values that do not
fit int64 the first cast to int64() is undefined behavior
in most languages and apparently in Golang:
http://c0x.coding-guidelines.com/6.3.1.4.pdf

This means the value of int64(float64(2^63)) can end up as either
-9223372036854775808 or 9223372036854775807.
From experimentation, it appears compiler optimization
determines the result.

The value is then casted back to float64 and matched against
the original float64, which may or may not pass. Depending of FPU
rounding mode for IEEE754-Doubles any input above 9223372036854775296
may get casted to 9223372036854775808.0.

Adapt the unit test for "uint64 big" to not feed a big float64 and enter
the problem cases. Instead pass the nearest rounded value of 2^63
as a uint64 and expect to receive the same result:
  bigUint64 = ((uint64(1) << 63) + 500) / 1000 * 1000
@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Nov 12, 2020
@k8s-ci-robot k8s-ci-robot added sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Nov 12, 2020
@neolit123
Copy link
Member Author

neolit123 commented Nov 12, 2020

while jsonToYAMLValue is doing something that is not recommended, it appears to match existing logic in https://github.com/go-yaml/yaml, so i left it untouched.

/kind bug
/sig api-machinery
/priority backlog
/cc @sttts

@k8s-ci-robot k8s-ci-robot requested a review from sttts November 12, 2020 19:15
@k8s-ci-robot k8s-ci-robot added kind/bug Categorizes issue or PR as related to a bug. priority/backlog Higher priority than priority/awaiting-more-evidence. labels Nov 12, 2020
@neolit123 neolit123 mentioned this pull request Nov 12, 2020
@hakman hakman mentioned this pull request Nov 13, 2020
@dims
Copy link
Member

dims commented Jan 24, 2021

tested this on a real arm64 box:

[ubuntu@ip-172-31-41-104 23:44] ~/go/src/sigs.k8s.io/yaml ⟩ uname -a
Linux ip-172-31-41-104 5.4.0-1035-aws #37-Ubuntu SMP Wed Jan 6 21:02:01 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux

@dims
Copy link
Member

dims commented Jan 24, 2021

cpu info

[ubuntu@ip-172-31-41-104 23:46] ~/go/src/sigs.k8s.io/yaml ⟩ lscpu
Architecture:                    aarch64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
CPU(s):                          8
On-line CPU(s) list:             0-7
Thread(s) per core:              1
Core(s) per socket:              8
Socket(s):                       1
NUMA node(s):                    1
Vendor ID:                       ARM
Model:                           1
Model name:                      Neoverse-N1
Stepping:                        r3p1
BogoMIPS:                        243.75
L1d cache:                       512 KiB
L1i cache:                       512 KiB
L2 cache:                        8 MiB
L3 cache:                        32 MiB
NUMA node0 CPU(s):               0-7
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:        Mitigation; __user pointer sanitization
Vulnerability Spectre v2:        Not affected
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected
Flags:                           fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimdd
                                 p ssbs

@dims
Copy link
Member

dims commented Jan 24, 2021

/approve
/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jan 24, 2021
@k8s-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dims, neolit123

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 24, 2021
@k8s-ci-robot k8s-ci-robot merged commit 8f01418 into kubernetes-sigs:master Jan 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/backlog Higher priority than priority/awaiting-more-evidence. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test failed on arm64
3 participants