Skip to content

utils: Enforce string max_length in UTF-8 bytes - #158

Open
cmuellner wants to merge 1 commit into
OpenPrintTag:mainfrom
cmuellner:string_utf8_length
Open

cmuellner wants to merge 1 commit into
OpenPrintTag:mainfrom
cmuellner:string_utf8_length

Conversation

@cmuellner

Copy link
Copy Markdown

utils: Enforce string max_length in UTF-8 bytes

Problem

The specification defines the X in string:X as the maximum length
in bytes (see "NFC data format", encoding rules), and strings are
encoded as UTF-8. The reference implementation however checked the number
of characters in StringField.encode():

assert len(result) <= self.max_len

For ASCII-only strings both are the same, but strings with multi-byte
characters could exceed the byte limit without any error. For example,
the Japanese material name

シルクPLA トリプルカラー ゴールド&シルバー&カッパー

("Silk PLA Tri-Color Gold & Silver & Copper") has 29 characters but
77 UTF-8 bytes. It was accepted for material_name (string:63) and
written to the tag, and rec_info --validate did not report it either.

Change

StringField.encode() now checks the length of the UTF-8 encoded string
and reports the actual and allowed size on failure:

AssertionError: String is 77 B long when UTF-8 encoded, max 63 B allowed
Field 10 material_name

Tests

  • tests/specific/string_too_long_utf8.yaml: the name above must be
    rejected. This test fails without the fix.
  • tests/encode_decode/06_*: the Japanese material name
    シルクPLA+ デュアルカラー ゴールド&シルバー (25 characters, exactly
    63 bytes) must be encoded and decoded unchanged.

python3 tests/run_tests.py passes, utils/gen_schema.py produces no
changes, and the sample data in docs_src/sample_data still encodes.

The specification defines the X in string:X as the maximum length in
bytes, and strings are encoded as UTF-8. StringField.encode() however
compared the number of characters against max_length, so strings with
multi-byte characters could exceed the byte limit unnoticed.

For example, the Japanese material name
"シルクPLA トリプルカラー ゴールド&シルバー&カッパー"
("Silk PLA Tri-Color Gold & Silver & Copper") has 29 characters but
77 bytes, and was accepted for material_name (string:63).

Check the length of the UTF-8 encoded string instead and report the
actual and allowed size on failure.

Add a test that the above name is rejected, and an encode/decode test
with a multi-byte material name exactly at the 63-byte limit.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant