Repository: secdev/scapy

Issue:
AutomotiveTestCaseExecutor.scan() overflows time_t on 32-bit machines
### Brief description

It's extracted from https://github.com/secdev/scapy/issues/3847 because that thread is already huge and appears to mostly cover big endian issues at this point.

The "AutomotiveTestCaseExecutorConfiguration " test fails on 32-bit machines on Debian Unstable (https://github.com/secdev/scapy/issues/3847#issuecomment-1414092415) and Fedora (https://github.com/evverx/scapy/pull/1/checks?check_run_id=11083081330) with
```sh
######
## AutomotiveTestCaseExecutorConfiguration tests
######


###(038)=[failed] TestCase scan

�[34m�[1m>>> �[0mtc_executed = False
�[34m�[1m>>> �[0m
�[34m�[1m>>> �[0mclass GeneratedTestCase(MyTestCase):
...     def execute(self, socket, state, **kwargs):
...         assert kwargs["local_kwarg"] == "world"
...         global tc_executed
...         tc_executed = True
...         self._state_completed[state] = True
...         return True
... 
�[34m�[1m>>> �[0m
�[34m�[1m>>> �[0mclass TestCase43(MyTestCase, TestCaseGenerator):
...     def execute(self, socket, state, **kwargs):
...         self._state_completed[state] = True
...         return True
...     def get_generated_test_case(self):
...         return GeneratedTestCase()
... 
�[34m�[1m>>> �[0m
�[34m�[1m>>> �[0mtce = Scanner(MockSock(), test_cases=[TestCase43],
...               GeneratedTestCase_kwargs={"local_kwarg": "world"})
�[34m�[1m>>> �[0m
�[34m�[1m>>> �[0massert len(tce.final_states) == 1
�[34m�[1m>>> �[0massert len(tce.configuration.test_cases) == 1
�[34m�[1m>>> �[0m
�[34m�[1m>>> �[0mtce.scan()
Traceback (most recent call last):
  File "<input>", line 2, in <module>
  File "/tmp/autopkgtest-lxc.7d8x7nsw/downtmp/autopkgtest_tmp/src/scapy/contrib/automotive/scanner/executor.py", line 271, in scan
    log_automotive.debug("Set kill_time to %s" % time.ctime(kill_time))
                                                 ^^^^^^^^^^^^^^^^^^^^^
OverflowError: timestamp out of range for platform time_t



�[31mUTscapy ended with error code 1�[0m
```

As far as I can tell when the scan method is called something like `time.time() + 0xffffffff` is passed to `time.ctime` and it bails out because it's much larger than `2 ** 31 - 1`.

### Scapy version

6ae0e87f

### Python version

3.11.1

### Operating system

Debian Unstable

### Additional environment information

_No response_

### How to reproduce

It can be reproduced by running the unit tests on i386.

### Actual result

_No response_

### Expected result

_No response_

### Related resources

_No response_


Discussion:

Resolving patch:
diff --git a/scapy/contrib/automotive/scanner/enumerator.py b/scapy/contrib/automotive/scanner/enumerator.py
--- a/scapy/contrib/automotive/scanner/enumerator.py
+++ b/scapy/contrib/automotive/scanner/enumerator.py
@@ -288,7 +288,7 @@ def execute(self, socket, state, **kwargs):
 
         # log_automotive.debug("[i] Using iterator %s in state %s", it, state)
 
-        start_time = time.time()
+        start_time = time.monotonic()
         log_automotive.debug(
             "Start execution of enumerator: %s", time.ctime(start_time))
 
@@ -309,7 +309,7 @@ def execute(self, socket, state, **kwargs):
                         "Finished execution count of enumerator")
                     return
 
-            if (start_time + execution_time) < time.time():
+            if (start_time + execution_time) < time.monotonic():
                 log_automotive.debug(
                     "[i] Finished execution time of enumerator: %s",
                     time.ctime())
diff --git a/scapy/contrib/automotive/scanner/executor.py b/scapy/contrib/automotive/scanner/executor.py
--- a/scapy/contrib/automotive/scanner/executor.py
+++ b/scapy/contrib/automotive/scanner/executor.py
@@ -184,7 +184,7 @@ def execute_test_case(self, test_case, kill_time=None):
             test_case_kwargs = dict()
 
         if kill_time:
-            max_execution_time = max(int(kill_time - time.time()), 5)
+            max_execution_time = max(int(kill_time - time.monotonic()), 5)
             cur_execution_time = test_case_kwargs.get("execution_time", 1200)
             test_case_kwargs["execution_time"] = min(max_execution_time,
                                                      cur_execution_time)
@@ -258,16 +258,19 @@ def scan(self, timeout=None):
         :return: None
         """
         self.configuration.stop_event.clear()
-        kill_time = time.time() + (timeout or 0xffffffff)
+        if timeout is None:
+            kill_time = None
+        else:
+            kill_time = time.monotonic() + timeout
         log_automotive.debug("Set kill_time to %s" % time.ctime(kill_time))
-        while kill_time > time.time():
+        while kill_time is None or kill_time > time.monotonic():
             test_case_executed = False
             log_automotive.info("[i] Scan progress %0.2f", self.progress())
             log_automotive.debug("[i] Scan paths %s", self.state_paths)
             for p, test_case in product(
                     self.state_paths, self.configuration.test_cases):
                 log_automotive.info("Scan path %s", p)
-                terminate = kill_time <= time.time()
+                terminate = kill_time and kill_time <= time.monotonic()
                 if terminate or self.configuration.stop_event.is_set():
                     log_automotive.debug(
                         "Execution time exceeded. Terminating scan!")


Test patch: