git: ea6d16926666 - main - ping: Avoid reporting negative time statistics

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Sun, 19 Mar 2023 16:33:29 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=ea6d16926666a717e2c0a898b954d1477ac34804

commit ea6d16926666a717e2c0a898b954d1477ac34804
Author:     Jose Luis Duran <jlduran@gmail.com>
AuthorDate: 2023-02-09 23:38:54 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-03-19 16:24:06 +0000

    ping: Avoid reporting negative time statistics
    
    Display a warning when the time goes back.
    
    PR:             192417
    Reviewed by:    markj
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D38480
---
 sbin/ping/ping.c             |  8 +++++++-
 sbin/ping/tests/test_ping.py | 30 +++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 299b582e29c1..6b82fe3da9de 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -1212,8 +1212,14 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
 				tv1.tv_sec = ntohl(tv32.tv32_sec);
 				tv1.tv_nsec = ntohl(tv32.tv32_nsec);
 				timespecsub(tv, &tv1, tv);
- 				triptime = ((double)tv->tv_sec) * 1000.0 +
+				triptime = ((double)tv->tv_sec) * 1000.0 +
 				    ((double)tv->tv_nsec) / 1000000.0;
+				if (triptime < 0) {
+					warnx("time of day goes back (%.3f ms),"
+					    " clamping time to 0",
+					    triptime);
+					triptime = 0;
+				}
 				tsum += triptime;
 				tsumsq += triptime * triptime;
 				if (triptime < tmin)
diff --git a/sbin/ping/tests/test_ping.py b/sbin/ping/tests/test_ping.py
index 7040faa71a5d..f1c961c5b551 100644
--- a/sbin/ping/tests/test_ping.py
+++ b/sbin/ping/tests/test_ping.py
@@ -268,6 +268,7 @@ def redact(output):
         ("hlim=[0-9]*", "hlim="),
         ("ttl=[0-9]*", "ttl="),
         ("time=[0-9.-]*", "time="),
+        ("\(-[0-9\.]+[0-9]+ ms\)", "(- ms)"),
         ("[0-9\.]+/[0-9.]+", "/"),
     ]
     for pattern, repl in pattern_replacements:
@@ -1209,6 +1210,32 @@ ping: quoted data too short (28 bytes) from 192.0.2.2
             },
             id="_3_1_special_udp",
         ),
+        pytest.param(
+            {
+                "src": "192.0.2.1",
+                "dst": "192.0.2.2",
+                "icmp_type": 0,
+                "icmp_code": 0,
+                "special": "warp",
+            },
+            {
+                "returncode": 0,
+                "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+                "stderr": """\
+ping: time of day goes back (- ms), clamping time to 0
+""",
+                "redacted": True,
+            },
+            id="_0_0_special_warp",
+        ),
     ]
 
     @pytest.mark.parametrize("pinger_kargs, expected", pinger_testdata)
@@ -1221,6 +1248,7 @@ ping: quoted data too short (28 bytes) from 192.0.2.2
         assert ping.returncode == expected["returncode"]
         if expected["redacted"]:
             assert redact(ping.stdout) == expected["stdout"]
+            assert redact(ping.stderr) == expected["stderr"]
         else:
             assert ping.stdout == expected["stdout"]
-        assert ping.stderr == expected["stderr"]
+            assert ping.stderr == expected["stderr"]