Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Unreleased

### Bug fixes

* `get_string` and `get_wstring` now raise `ValueError` when the buffer is shorter than the declared current length,
instead of silently returning a truncated value (#945).
* `get_wstring` compared the declared maximum in bytes with the 16382-character limit, so any WSTRING with a
capacity of 8192 characters or more was rejected, including ones written by `set_wstring` (#923).
* The get-block-info request now places the trailing `A` after the block number, as native Snap7 does
Expand Down
8 changes: 8 additions & 0 deletions snap7/util/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ def get_string(bytearray_: Buffer, byte_index: int, encoding: str = "latin-1") -
"String contains {str_length} chars, but max. {max_string_size} chars are expected or is "
"larger than 254. Bytearray doesn't seem to be a valid string."
)
if byte_index + 2 + str_length > len(bytearray_):
raise ValueError(
f"String contains {str_length} chars, but only {len(bytearray_) - byte_index - 2} bytes are in the buffer"
)
raw = bytes(bytearray_[byte_index + 2 : byte_index + 2 + str_length])
return raw.decode(encoding)

Expand Down Expand Up @@ -795,4 +799,8 @@ def get_wstring(bytearray_: Buffer, byte_index: int) -> str:
)

wstr_bytes = wstr_chars * 2
if wstring_start + wstr_bytes > len(bytearray_):
raise ValueError(
f"WString contains {wstr_chars} chars, but only {len(bytearray_) - wstring_start} bytes are in the buffer"
)
return bytes(bytearray_[wstring_start : wstring_start + wstr_bytes]).decode("utf-16-be")
15 changes: 14 additions & 1 deletion tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from snap7 import DB, Row
from snap7.type import Area, WordLen
from snap7.util import get_byte, get_time, get_fstring, get_int
from snap7.util import get_byte, get_time, get_fstring, get_int, get_string, get_wstring
from snap7.util import set_byte, set_time, set_fstring, set_int
from snap7.util.db import print_row

Expand Down Expand Up @@ -1495,3 +1495,16 @@ def test_write_with_row_offset(self) -> None:

if __name__ == "__main__":
unittest.main()


@pytest.mark.parametrize(
"func,data",
[
(get_string, bytearray([3, 3, 65])),
(get_string, bytearray([5, 4, 65, 66])),
(get_wstring, bytearray([0, 3, 0, 3, 0, 65, 0, 66])),
],
)
def test_get_string_short_buffer_raises(func, data) -> None: # type: ignore[no-untyped-def]
with pytest.raises(ValueError):
func(data, 0)
Loading