Package: iputils-ping
Version: 3:20180629-2

Usually, ping reports times like 17.1 ms, but every once in a while it 
reports a trip time of, say, 17.10 ms. I expect to always get 3 
significant digits, not sometimes 4. Here is a transcript:

$ ping 1.1.1.1
(...)
64 bytes from 1.1.1.1: icmp_seq=5318 ttl=53 time=16.4 ms
64 bytes from 1.1.1.1: icmp_seq=5319 ttl=53 time=17.1 ms
64 bytes from 1.1.1.1: icmp_seq=5320 ttl=53 time=13.8 ms
64 bytes from 1.1.1.1: icmp_seq=5321 ttl=53 time=17.10 ms
64 bytes from 1.1.1.1: icmp_seq=5322 ttl=53 time=13.9 ms
(...)

I traced this back to function gather_statistics in file ping_common.c. 
The current rounding is in these lines:

$ grep -n 'triptime >= 10000)' -B 3 -A 9 ping_common.c
855-            if (timing) {
856-                    if (triptime >= 100000)
857-                            printf(" time=%ld ms", (triptime+500)/1000);
858:                    else if (triptime >= 10000)
859-                            printf(" time=%ld.%01ld ms", triptime/1000,
860-                                   ((triptime%1000)+50)/100);
861-                    else if (triptime >= 1000)
862-                            printf(" time=%ld.%02ld ms", triptime/1000,
863-                                   ((triptime%1000)+5)/10);
864-                    else
865-                            printf(" time=%ld.%03ld ms", triptime/1000,
866-                                   triptime%1000);
867-            }

The bug happens for example with triptime = 17981:
    triptime/1000 = 17981/1000
                  = 17 (seconds)
    (triptime%1000)+50)/100 = (17981%1000)+50)/100
                            = (  981      +50)/100
                            =   1031          /100
                            =   10 (tenths of a second)

So, while 17981 ms should have been converted to 18.0 seconds, it is 
converted to 17.10 seconds.

One way of fixing it:

                if (timing) {
                        if (triptime >= 100000 - 50)
                                printf(" time=%ld ms", (triptime+500)/1000);
                        else if (triptime >= 10000 - 5)
                                printf(" time=%ld.%01ld ms", (triptime+50)/1000,
                                       ((triptime+50)%1000)/100);
                        else if (triptime >= 1000)
                                printf(" time=%ld.%02ld ms", (triptime+5)/1000,
                                       ((triptime+5)%1000)/10);
                        else
                                printf(" time=%ld.%03ld ms", triptime/1000,
                                       triptime%1000);
                }

I fixed the triptime thresholds so the output is consistent, added the 
+50/+5 to the whole milliseconds so it gets rounded as well, and moved 
the +50/+5 of the fractional milliseconds to the correct place.

The code is far less readable, so may I suggest that you consider 
rewriting the code so it is better maintainable than my suggested fix?

Attachment: signature.asc
Description: PGP signature

Reply via email to