dhylands / rshell

Remote Shell for MicroPython
MIT License
955 stars 136 forks source link

Catch exception raised by socket.gethostbyname() if the serial port name is too long #186

Closed ironss-iotec closed 2 years ago

ironss-iotec commented 2 years ago

When rshell tries to connect to a board, it passes the name of the port to socket.gethostbyname() as the hostname, to check whether it should use telnet or serial. If the serial port name is too long (>63 characters), this function raises UnicodeError, with the description "label too long".

This is reported as Python issue https://bugs.python.org/issue32958. This issue indicates that the behaviour is correct (components between dots in a hostname must be 63 character of less), but it might be better to raise socket.gaierror or ValueError rather than UnicodeError, but decided that there would be little advantage in doing so. UnicodeError is a subclass of ValueError

This issue has been around since 2018, so it is unlikely to be changed.

The solution is to catch ValueError (or UnicodeError) in connect() function in main.py, as well as socket.gaierror. This is the correct solution, as rshell is truely passing an invalid hostname to socket.gethostbyname().

stephen@xxx:~$ rshell --port /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --baud 115200 ls
Using buffer-size of 32
Traceback (most recent call last):
  File "/usr/lib/python3.10/encodings/idna.py", line 167, in encode
    raise UnicodeError("label too long")
UnicodeError: label too long

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/stephen/workspace/rshell/./r.py", line 5, in <module>
    main.main()
  File "/home/stephen/workspace/rshell/rshell/main.py", line 3091, in main
    real_main()
  File "/home/stephen/workspace/rshell/rshell/main.py", line 3053, in real_main
    connect(args.port, baud=args.baud, wait=args.wait, user=args.user, password=args.password)
  File "/home/stephen/workspace/rshell/rshell/main.py", line 1390, in connect
    ip_address = socket.gethostbyname(port)
UnicodeError: encoding with 'idna' codec failed (UnicodeError: label too long)
dhylands commented 2 years ago

Looks good - thanks.