break
packet = self.buffer[2:frameend]
self.buffer = self.buffer[frameend + 2 :]
+ if len(packet) < 2: # frameend comes too early
+ log.warning("Packet too short: %s", packet)
+ break
if proto_of_message(packet) == LOGIN.PROTO:
- self.imei = parse_message(packet).imei
- log.info(
- "LOGIN from fd %d (IMEI %s)", self.sock.fileno(), self.imei
- )
+ msg = parse_message(packet)
+ if isinstance(msg, LOGIN): # Can be unparseable
+ self.imei = msg.imei
+ log.info(
+ "LOGIN from fd %d (IMEI %s)",
+ self.sock.fileno(),
+ self.imei,
+ )
msgs.append((when, self.addr, packet))
return msgs
except OSError as e:
log.error(
"Sending to fd %d (IMEI %s): %s",
- self.sock.fileno,
+ self.sock.fileno(),
self.imei,
e,
)
# Default response for ACK, can also respond with STOP_UPLOAD
def in_decode(self, length: int, payload: bytes) -> None:
- self.imei = payload[:-1].hex()
- self.ver = unpack("B", payload[-1:])[0]
+ self.imei = payload[:16].hex()
+ self.ver = payload[16]
class SUPERVISION(GPS303Pkt):
length, proto = unpack("BB", packet[:2])
payload = packet[2:]
if proto not in CLASSES:
- cause: Union[DecodeError, ValueError] = ValueError(
+ cause: Union[DecodeError, ValueError, IndexError] = ValueError(
f"Proto {proto} is unknown"
)
else:
return CLASSES[proto].In(length, payload)
else:
return CLASSES[proto].Out(length, payload)
- except DecodeError as e:
+ except (DecodeError, ValueError, IndexError) as e:
cause = e
if is_incoming:
retobj = UNKNOWN.In(length, payload)
from random import Random
from socket import getaddrinfo, socket, AF_INET6, MSG_DONTWAIT, SOCK_STREAM
+from time import sleep
+from typing import Optional
import unittest
from .common import TestWithServers
self.sock.connect(skadr)
def tearDown(self) -> None:
+ sleep(1) # give collector some time
+ self._send_and_drain(None)
self.sock.close()
print("finished fuzzing")
super().tearDown()
- def test_fuzz(self) -> None:
+ def _send_and_drain(self, buf: Optional[bytes]) -> None:
+ if buf is not None:
+ self.sock.send(buf)
+ try:
+ self.sock.recv(4096, MSG_DONTWAIT)
+ except BlockingIOError:
+ pass
+
+ def test_stream(self) -> None:
for _ in range(REPEAT):
size = self.rnd.randint(1, 5000)
buf = self.rnd.randbytes(size)
- self.sock.send(buf)
- try:
- self.sock.recv(4096, MSG_DONTWAIT)
- except BlockingIOError:
- pass
+ self._send_and_drain(buf)
+
+ def test_msgs(self) -> None:
+ for _ in range(REPEAT):
+ size = self.rnd.randint(0, 300)
+ buf = b"xx" + self.rnd.randbytes(size) + b"\r\n"
+ self._send_and_drain(buf)
if __name__ == "__main__":