From 71b2dc50b72319cd6652f827cd65e4ed2fc43f32 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 30 Oct 2024 16:37:42 +0000 Subject: [PATCH] library: move check for valid UTF-8 after de-escaping CODE128: fix bad index 0 -> i in `c128_glyph_count()` --- ChangeLog | 1 + backend/code128.c | 2 +- backend/library.c | 13 ++++------ backend/tests/test_code128.c | 49 ++++++++++++++++++------------------ backend/tests/test_library.c | 35 ++++++++++++++------------ 5 files changed, 51 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8cbfce0..d1c3b50d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -58,6 +58,7 @@ Bugs - QZint: fix legacy width and security level getters/setters, MR #158, props Philip Ye - CODE128: fix extended char latching when exactly 3 extended chars at end +- library: need to check for valid UTF-8 after de-escaping Version 2.13.0 (2023-12-18) diff --git a/backend/code128.c b/backend/code128.c index fd86afbc..83c1d13b 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -346,7 +346,7 @@ static int c128_glyph_count(const unsigned char source[], const int length, cons for (i = 0; i < length; i++) { if (set[i] != current_set) { /* Latch different code set */ - switch (set[0]) { + switch (set[i]) { case 'A': case 'b': /* Manual switching can cause immediate shift */ if (current_set != 'A') { diff --git a/backend/library.c b/backend/library.c index 97ea9ac0..82b33418 100644 --- a/backend/library.c +++ b/backend/library.c @@ -1161,14 +1161,6 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ } } - if ((symbol->input_mode & 0x07) == UNICODE_MODE) { - for (i = 0; i < seg_count; i++) { - if (!is_valid_utf8(local_segs[i].source, local_segs[i].length)) { - return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 245, "Invalid UTF-8 in input"); - } - } - } - local_sources = (unsigned char *) z_alloca(total_len + seg_count); /* Copy input, de-escaping if required */ @@ -1199,6 +1191,11 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ } if ((symbol->input_mode & 0x07) == UNICODE_MODE) { + for (i = 0; i < seg_count; i++) { + if (!is_valid_utf8(local_segs[i].source, local_segs[i].length)) { + return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 245, "Invalid UTF-8 in input"); + } + } /* Only strip BOM on first segment */ strip_bom(local_segs[0].source, &local_segs[0].length); } diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index 614a85a3..4ae9968f 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -53,30 +53,31 @@ static void test_large(const testCtx *const p_ctx) { /* 0*/ { BARCODE_CODE128, -1, "A", 99, 0, 1124, "" }, /* 1*/ { BARCODE_CODE128, -1, "A", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, /* 2*/ { BARCODE_CODE128, -1, "A", 257, ZINT_ERROR_TOO_LONG, -1, "Error 340: Input length 257 too long (maximum 256)" }, - /* 3*/ { BARCODE_CODE128, READER_INIT, "A", 99, 0, 1135, "" }, - /* 4*/ { BARCODE_CODE128, READER_INIT, "A", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, - /* 5*/ { BARCODE_CODE128, READER_INIT, "A", 257, ZINT_ERROR_TOO_LONG, -1, "Error 340: Input length 257 too long (maximum 256)" }, - /* 6*/ { BARCODE_CODE128, -1, "\351A", 66, 0, 1124, "" }, - /* 7*/ { BARCODE_CODE128, -1, "\351A", 67, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 101 symbol characters (maximum 99)" }, /* 67 chars (+ 34 shifts) */ - /* 8*/ { BARCODE_CODE128, -1, "\351", 97, 0, 1124, "" }, /* Less 2 FNC4s for latch */ - /* 9*/ { BARCODE_CODE128, -1, "\351", 98, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, - /* 10*/ { BARCODE_CODE128, -1, "0", 198, 0, 1124, "" }, - /* 11*/ { BARCODE_CODE128, -1, "0", 199, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 101 symbol characters (maximum 99)" }, - /* 12*/ { BARCODE_CODE128, -1, "0", 257, ZINT_ERROR_TOO_LONG, -1, "Error 340: Input length 257 too long (maximum 256)" }, - /* 13*/ { BARCODE_CODE128AB, -1, "A", 99, 0, 1124, "" }, - /* 14*/ { BARCODE_CODE128AB, -1, "A", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, - /* 15*/ { BARCODE_CODE128AB, -1, "0", 99, 0, 1124, "" }, - /* 16*/ { BARCODE_CODE128AB, -1, "0", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, - /* 17*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1, ZINT_WARN_HRT_TRUNCATED, 1135, "Warning 844: Human Readable Text truncated" }, /* 196 nos + 3 FNC1s */ - /* 18*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 101 symbol characters (maximum 99)" }, /* 196 nos + CodeA + single no. + 3 FNC1s */ - /* 19*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 100 symbol characters (maximum 99)" }, /* 198 nos + 3 FNC1s */ - /* 20*/ { BARCODE_GS1_128, -1, "A", 257, ZINT_ERROR_TOO_LONG, -1, "Error 342: Input length 257 too long (maximum 256)" }, - /* 21*/ { BARCODE_EAN14, -1, "1234567890123", -1, 0, 134, "" }, - /* 22*/ { BARCODE_EAN14, -1, "12345678901234", -1, ZINT_ERROR_TOO_LONG, -1, "Error 347: Input length 14 too long (maximum 13)" }, - /* 23*/ { BARCODE_NVE18, -1, "12345678901234567", -1, 0, 156, "" }, - /* 24*/ { BARCODE_NVE18, -1, "123456789012345678", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 17)" }, - /* 25*/ { BARCODE_HIBC_128, -1, "1", 110, 0, 684, "" }, - /* 26*/ { BARCODE_HIBC_128, -1, "1", 111, ZINT_ERROR_TOO_LONG, -1, "Error 202: Input length 111 too long for HIBC LIC (maximum 110)" }, + /* 3*/ { BARCODE_CODE128, -1, "abcd\201\202\203\204", 58, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, + /* 4*/ { BARCODE_CODE128, READER_INIT, "A", 99, 0, 1135, "" }, + /* 5*/ { BARCODE_CODE128, READER_INIT, "A", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, + /* 6*/ { BARCODE_CODE128, READER_INIT, "A", 257, ZINT_ERROR_TOO_LONG, -1, "Error 340: Input length 257 too long (maximum 256)" }, + /* 7*/ { BARCODE_CODE128, -1, "\351A", 66, 0, 1124, "" }, + /* 8*/ { BARCODE_CODE128, -1, "\351A", 67, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 101 symbol characters (maximum 99)" }, /* 67 chars (+ 34 shifts) */ + /* 9*/ { BARCODE_CODE128, -1, "\351", 97, 0, 1124, "" }, /* Less 2 FNC4s for latch */ + /* 10*/ { BARCODE_CODE128, -1, "\351", 98, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, + /* 11*/ { BARCODE_CODE128, -1, "0", 198, 0, 1124, "" }, + /* 12*/ { BARCODE_CODE128, -1, "0", 199, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 101 symbol characters (maximum 99)" }, + /* 13*/ { BARCODE_CODE128, -1, "0", 257, ZINT_ERROR_TOO_LONG, -1, "Error 340: Input length 257 too long (maximum 256)" }, + /* 14*/ { BARCODE_CODE128AB, -1, "A", 99, 0, 1124, "" }, + /* 15*/ { BARCODE_CODE128AB, -1, "A", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, + /* 16*/ { BARCODE_CODE128AB, -1, "0", 99, 0, 1124, "" }, + /* 17*/ { BARCODE_CODE128AB, -1, "0", 100, ZINT_ERROR_TOO_LONG, -1, "Error 341: Input too long, requires 100 symbol characters (maximum 99)" }, + /* 18*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1, ZINT_WARN_HRT_TRUNCATED, 1135, "Warning 844: Human Readable Text truncated" }, /* 196 nos + 3 FNC1s */ + /* 19*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 101 symbol characters (maximum 99)" }, /* 196 nos + CodeA + single no. + 3 FNC1s */ + /* 20*/ { BARCODE_GS1_128, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 100 symbol characters (maximum 99)" }, /* 198 nos + 3 FNC1s */ + /* 21*/ { BARCODE_GS1_128, -1, "A", 257, ZINT_ERROR_TOO_LONG, -1, "Error 342: Input length 257 too long (maximum 256)" }, + /* 22*/ { BARCODE_EAN14, -1, "1234567890123", -1, 0, 134, "" }, + /* 23*/ { BARCODE_EAN14, -1, "12345678901234", -1, ZINT_ERROR_TOO_LONG, -1, "Error 347: Input length 14 too long (maximum 13)" }, + /* 24*/ { BARCODE_NVE18, -1, "12345678901234567", -1, 0, 156, "" }, + /* 25*/ { BARCODE_NVE18, -1, "123456789012345678", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 17)" }, + /* 26*/ { BARCODE_HIBC_128, -1, "1", 110, 0, 684, "" }, + /* 27*/ { BARCODE_HIBC_128, -1, "1", 111, ZINT_ERROR_TOO_LONG, -1, "Error 202: Input length 111 too long for HIBC LIC (maximum 110)" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index 937f5150..aadab815 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -196,22 +196,25 @@ static void test_checks(const testCtx *const p_ctx) { /*132*/ { BARCODE_LAST + 1, -1, "1", -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 206: Symbology out of range", BARCODE_CODE128 }, /*133*/ { BARCODE_LAST + 1, -1, "1", -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 }, /*134*/ { BARCODE_CODE128, -1, "\200", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8 in input", -1 }, - /*135*/ { BARCODE_GS1_128, -1, "[01]12345678901234", -1, GS1_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_NONCOMPLIANT, "Warning 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, - /*136*/ { BARCODE_GS1_128, -1, "[01]12345678901234", -1, GS1_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_NONCOMPLIANT, "Error 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, - /*137*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, "", -1 }, - /*138*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, - /*139*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_USES_ECI, "Error 222: Encoded data includes ECI 13", -1 }, - /*140*/ { BARCODE_CODEONE, -1, "[01]12345678901231", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 512: ECI ignored for GS1 mode", -1 }, - /*141*/ { BARCODE_CODEONE, -1, "[01]12345678901231", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 512: ECI ignored for GS1 mode", -1 }, - /*142*/ { BARCODE_CODEONE, -1, "[01]12345678901234", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 512: ECI ignored for GS1 mode", -1 }, /* Warning in encoder overrides library warnings */ - /*143*/ { BARCODE_CODEONE, -1, "[01]12345678901234", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_NONCOMPLIANT, "Error 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, /* But not errors */ - /*144*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, "", -1 }, - /*145*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, - /*146*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_USES_ECI, "Error 222: Encoded data includes ECI 13", -1 }, - /*147*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 503: Error correction level '6' out of range (1 to 4), ignoring", -1 }, - /*148*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 503: Error correction level '6' out of range (1 to 4)", -1 }, - /*149*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, /* ECI warning trumps all other warnings */ - /*150*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 503: Error correction level '6' out of range (1 to 4)", -1 }, /* But not errors */ + /*135*/ { BARCODE_CODE128, -1, "\\o200", -1, UNICODE_MODE | ESCAPE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8 in input", -1 }, + /*136*/ { BARCODE_MAXICODE, -1, "\200", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8 in input", -1 }, + /*137*/ { BARCODE_MAXICODE, -1, "\\o200", -1, UNICODE_MODE | ESCAPE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8 in input", -1 }, + /*138*/ { BARCODE_GS1_128, -1, "[01]12345678901234", -1, GS1_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_NONCOMPLIANT, "Warning 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, + /*139*/ { BARCODE_GS1_128, -1, "[01]12345678901234", -1, GS1_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_NONCOMPLIANT, "Error 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, + /*140*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, "", -1 }, + /*141*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, + /*142*/ { BARCODE_QRCODE, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_USES_ECI, "Error 222: Encoded data includes ECI 13", -1 }, + /*143*/ { BARCODE_CODEONE, -1, "[01]12345678901231", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 512: ECI ignored for GS1 mode", -1 }, + /*144*/ { BARCODE_CODEONE, -1, "[01]12345678901231", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 512: ECI ignored for GS1 mode", -1 }, + /*145*/ { BARCODE_CODEONE, -1, "[01]12345678901234", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 512: ECI ignored for GS1 mode", -1 }, /* Warning in encoder overrides library warnings */ + /*146*/ { BARCODE_CODEONE, -1, "[01]12345678901234", -1, GS1_MODE, 3, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_NONCOMPLIANT, "Error 261: AI (01) position 14: Bad checksum '4', expected '1'", -1 }, /* But not errors */ + /*147*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, "", -1 }, + /*148*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, + /*149*/ { BARCODE_AZTEC, -1, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_USES_ECI, "Error 222: Encoded data includes ECI 13", -1 }, + /*150*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 503: Error correction level '6' out of range (1 to 4), ignoring", -1 }, + /*151*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, 13, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 503: Error correction level '6' out of range (1 to 4)", -1 }, + /*152*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, -1, ZINT_WARN_USES_ECI, "Warning 222: Encoded data includes ECI 13", -1 }, /* ECI warning trumps all other warnings */ + /*153*/ { BARCODE_AZTEC, 6, "ก", -1, UNICODE_MODE, -1, 0, 0, 0, 0, -1, -1, 0, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 503: Error correction level '6' out of range (1 to 4)", -1 }, /* But not errors */ }; const int data_size = ARRAY_SIZE(data); int i, length, ret;