MarketSquare / SSHLibrary

Robot Framework test library for SSH and SFTP
http://marketsquare.github.io/SSHLibrary/
Other
158 stars 139 forks source link

Write keyword is raising UnicodeDecodeError when the output is corrupted #465

Open uruun opened 2 months ago

uruun commented 2 months ago

The Read Until With Encoding Errors On Strict test is failing with UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfa in position 88: invalid start byte (the "position" can differ). Turns out that the corrupted output of the file is leaking to the Write keyword call. It makes Write fail depending on timing, if the output following Write is corrupted. Issue introduced in #431

 def _read_until(self, matcher, expected, timeout=None):
        timeout = TimeEntry(timeout) if timeout else self.config.get('timeout')
        max_time = time.time() + timeout.value
        while time.time() < max_time:
            undecoded = self._single_complete_read_to_buffer(max_time)  # <<<<< Reading into corrupted text
            if undecoded:
                self._receive_buffer += undecoded.decode(  # <<<<< Exception
                    self.config.encoding, "ignore"
                )
            match = matcher(self._receive_buffer)
            if match:
                if hasattr(match, "end"):
                    end = match.end()
                else:
                    end = self._receive_buffer.index(expected) + len(expected)
                output = self._receive_buffer[0:end]
                self._receive_buffer = self._receive_buffer[end:]
                return output
        output = self._receive_buffer
        self._receive_buffer = ""
        raise SSHClientException(f"No match found for '{expected}' in {timeout}\nOutput:\n{output}.")

If the read after Write reads beyond the written text into the corrupted part, the

undecoded = self._single_complete_read_to_buffer(max_time)

will read until timeout and the undecoded.decode will fail. The fix might be to try and decode as much of the beginning of the undecoded part as possible and then match.