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

Crash in YAxisRendererRadarChart #2356

Closed
owenbirdsall opened this issue Apr 13, 2017 · 12 comments
Closed

Crash in YAxisRendererRadarChart #2356

owenbirdsall opened this issue Apr 13, 2017 · 12 comments
Assignees

Comments

@owenbirdsall
Copy link

Crashes on line 137: axis.decimals = Int(ceil(-log10(interval)))

When interval is 0.
In my case this is happening when rawInterval is 0.05, interval then gets set to 0, and -log10(0) results in NaN which causes ceil to crash.

@liuxuan30
Copy link
Member

why rawInterval is 0.05 leads to interval 0?

@owenbirdsall
Copy link
Author

owenbirdsall commented Apr 14, 2017 via email

@owenbirdsall
Copy link
Author

owenbirdsall commented Apr 14, 2017

Sorry, it was range that was 0.05 not rawInterval. So when you have a range of 0.05, rawInterval becomes 0.0083* and in turn interval becomes 0. Which results in a crash.

@owenbirdsall
Copy link
Author

Presumably changing line 135 to:
if interval > 0 && interval < 1
Would fix the issue?

@liuxuan30
Copy link
Member

I need you to give more details on how this leads to crash, and what's the test data, so we can reproduce with ChartsDemo. There has been a long time for this kind of issue.

@owenbirdsall
Copy link
Author

owenbirdsall commented Apr 19, 2017

There is a vulnerability because of this piece of code on line 137 of YAxisRendererRadarChart:
axis.decimals = Int(ceil(-log10(interval)))

If you add the following code var x = Int(ceil(-log10(0))) to your demo it will crash.

There is no guard against interval being zero, and if it is zero it will cause a crash. As far as I can see there is nothing preventing data being used in a radar chart that can result in an interval of zero.

In my case I had a range of 0.05, which caused rawInterval to be 0.0083* and hence interval is zero... hence the crash.

A simple guard against zero whenever you use this Int(ceil(-log10(interval))) piece of code should fix your issues.

@liuxuan30
Copy link
Member

Why interval in your case is Int 0? It's supposed to be Double value.

I tried with 0.05 range like below, it still does not crash.

(lldb) po range
0.050000000000000003

(lldb) po rawInterval
0.01

(lldb) po interval
0.01

(lldb) po Int(ceil(-log10(interval)))
2

The interval is a float decimal value, not as Int 0.

@owenbirdsall
Copy link
Author

owenbirdsall commented Apr 19, 2017

It's not an integer, it's a double - but a double can still be zero (i.e. 0.0)
...and -log10(0.0) results in a NaN
...and ceil(NaN) causes a crash

I don't see anything in the code which guarantees that interval is > 0.0

@owenbirdsall
Copy link
Author

Here are the values I have in my debugger at the point of my crash:
screen shot 2017-04-19 at 11 21 32

@owenbirdsall
Copy link
Author

owenbirdsall commented Apr 19, 2017

From what I can see interval is >0.0 until it reaches the following block of code:

interval = floor(10 * intervalMagnitude)

This floor operation can cause interval to go to 0.0

@liuxuan30
Copy link
Member

liuxuan30 commented Apr 20, 2017

Well range=0.05 will not crash, but range=0.3785 will. Looks like we missed some corner cases
As rawInterval is 0.06308, the interval is 0.06, and intervalMagnitude=0.01, intervalSigDigit=6

Now the problem is intervalSigDigit=6 will trigger:

        if intervalSigDigit > 5
        {
            // Use one order of magnitude higher, to avoid intervals like 0.9 or
            // 90
            interval = floor(10 * intervalMagnitude)
        }

and unfortunately, floor(10 * 0.01) is 0.0 indeed

I can't say this is a bug or design flaw, but right now you can use

interval = floor(10 * intervalMagnitude) == 0.0 ? interval : floor(10 * intervalMagnitude)

to fix. I will add a PR for this later.

Note, interval can be replaced with intervalMagnitude * 5 (e.g. to get 0.05 rather than 0.06, 0.08) or whatever interval looks good to you.

@owenbirdsall
Copy link
Author

Thanks for looking into this, much appreciated.

pouriaalmassi added a commit to MoneyBrilliant/Charts that referenced this issue Jun 9, 2017
liuxuan30 added a commit that referenced this issue Jan 15, 2018
fix #2356 crash if floor(10.0 * intervalMagnitude) is 0.0
philipengberg pushed a commit to tonsser/Charts that referenced this issue Jan 19, 2018
When `floor(10.0 * intervalMagnitude)` is 0.0, we use the old value to avoid crash at `axis.decimals = Int(ceil(-log10(interval)))`
kzyryanov pushed a commit to fishbrain/Charts that referenced this issue Feb 20, 2018
When `floor(10.0 * intervalMagnitude)` is 0.0, we use the old value to avoid crash at `axis.decimals = Int(ceil(-log10(interval)))`
kalmurzayev pushed a commit to kalmurzayev/Charts that referenced this issue Feb 26, 2018
When `floor(10.0 * intervalMagnitude)` is 0.0, we use the old value to avoid crash at `axis.decimals = Int(ceil(-log10(interval)))`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants