From 885cf0610d97ce7ca8baf4a11f8bfc3694b8ae40 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 5 Dec 2023 19:00:01 +0000 Subject: [PATCH] QRCODE: fix `qr_in_alpha()` uneven percent check to be gs1 only, causing incorrect mode costings leading to version 40 `binlen` < lower version, triggering assert, ticket #300 (#15), props Andre Maute --- backend/qr.c | 10 ++++++---- backend/tests/test_qr.c | 40 ++++++++++++++++++++------------------ docs/manual.html | 5 ++++- docs/manual.pmd | 2 +- docs/manual.txt | 4 ++-- docs/templates/styles.html | 3 +++ docs/zint.1 | 2 +- docs/zint.1.pmd | 2 +- 8 files changed, 39 insertions(+), 29 deletions(-) diff --git a/backend/qr.c b/backend/qr.c index 44053801..5fed3c10 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -109,7 +109,7 @@ static int qr_in_alpha(const unsigned int ddata[], const int length, const int i *p_pcent = 0; } else { /* As above, uneven percents means will fit in alpha pair */ - *p_cost = !last || !(*p_pccnt & 1) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; + *p_cost = !last || (gs1 && !(*p_pccnt & 1)) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; } return 1; } @@ -136,11 +136,13 @@ static int qr_in_alpha(const unsigned int ddata[], const int length, const int i *p_pcent = two_alphas && gs1 && ddata[in_posn + 1] == '%'; /* 2nd char is percent */ *p_pccnt += *p_pcent; /* No-op unless `gs1` */ /* Uneven percents means will fit in alpha pair */ - *p_cost = two_alphas || !(*p_pccnt & 1) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; + *p_cost = two_alphas || (gs1 && !(*p_pccnt & 1)) ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; return 1; } -/*#define QR_DEBUG_DEFINE_MODE*/ /* For debugging costings */ +#if 0 +#define QR_DEBUG_DEFINE_MODE /* For debugging costings */ +#endif /* Indexes into qr_mode_types array (and state array) */ #define QR_N 0 /* Numeric */ @@ -292,7 +294,7 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le } #ifdef QR_DEBUG_DEFINE_MODE - printf(" curr"); + printf(" % 4d: curr", i); for (j = 0; j < QR_NUM_MODES; j++) { printf(" %c(%c)=%d", qr_mode_types[j], char_modes[cm_i + j], cur_costs[j]); } diff --git a/backend/tests/test_qr.c b/backend/tests/test_qr.c index 9c48c92f..1c176e8a 100644 --- a/backend/tests/test_qr.c +++ b/backend/tests/test_qr.c @@ -5250,7 +5250,7 @@ static void test_microqr_optimize(const testCtx *const p_ctx) { /* 5*/ { UNICODE_MODE, 1, 4, -1, "01a", 0, "43 30 31 61 00 00 EC 11 EC 11 EC 11 EC 11 EC 11", 1, 1, "B3" }, /* 6*/ { UNICODE_MODE, 1, -1, -1, "こんwa、αβ", 0, "46 82 B1 82 F1 77 61 66 00 10 FF 88 00 00 EC 11", 1, 1, "B6 K3" }, /* 7*/ { UNICODE_MODE, 1, -1, -1, "こんにwa、αβ", 0, "66 13 10 B8 85 25 09 DD 85 98 00 43 FE 20 00 00", 1, 1, "K3 B2 K3" }, - /* 8*/ { UNICODE_MODE, 1, 3, -1, "こんAB123\177", 0, "D0 4C 42 E2 A9 CD 05 E1 C2 FE 00", 1, 1, "K2 A5 B1" }, + /* 8*/ { UNICODE_MODE, 1, 3, -1, "こんAB123\177", 0, "D0 4C 42 E2 91 CD 06 3D C2 FE 00", 0, 1, "K2 A2 N3 B1; BWIPP different encodation (K2 A5 B1)" }, /* 9*/ { UNICODE_MODE, 1, 4, -1, "こんAB123\177", 0, "64 13 10 B8 92 9C D0 5E 1A 0B F8 00 EC 11 EC 11", 1, 1, "K2 A5 B1" }, /* 10*/ { DATA_MODE, 1, -1, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 EC 11 00", 0, 0, "B2; BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, /* 11*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", 1, 1, "K1" }, @@ -8121,7 +8121,7 @@ static void test_rmqr_optimize(const testCtx *const p_ctx) { /* 7*/ { UNICODE_MODE, 4, 11, "0123A", 0, "28 06 1A 12 80", 1, "N4 A1 (nayuki.io - alpha/numeric)" }, /* 8*/ { UNICODE_MODE, 4, 11, "0a", 0, "68 C1 84 00 EC", 1, "B2 (nayuki.io - numeric/byte)" }, /* 9*/ { UNICODE_MODE, 4, 11, "01a", 0, "24 05 96 10 EC", 1, "N2 B1 (nayuki.io - numeric/byte)" }, - /* 10*/ { UNICODE_MODE, 4, 11, "ABCa", 0, "46 73 4C 65 84", 0, "A3 B1 (nayuki.io - alphanumeric/byte); BWIPP different encodation (B4)" }, + /* 10*/ { UNICODE_MODE, 4, 11, "ABCa", 0, "71 05 09 0D 84", 1, "A4 (nayuki.io - alphanumeric/byte)" }, /* 11*/ { UNICODE_MODE, 2, 11, "ABCDa", 0, "48 73 51 4B 2C 20 EC", 1, "A4 B1 (same bits as B5)" }, /* 12*/ { UNICODE_MODE, 2, 24, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 0, "(48) 46 A9 52 9A A0 D5 42 66 E6 F8 A1 4F 62 3E 56 CC D4 40 2B 98 2C F1 AB 19 2E A2 F8 61", 1, " A26 N65 (nayuki.io - alpha/numeric)" }, /* 13*/ { UNICODE_MODE, 2, 21, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", ZINT_WARN_NONCOMPLIANT, "Warning (73) 65 11 DB DB 19 19 5B 88 1C 98 5D 1A 5B C8 20 F4 C8 0F 48 0C 4B 8B 24 D4 10 FB 97 6E", 1, "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, @@ -8748,21 +8748,21 @@ static void test_rmqr_encode_segs(const testCtx *const p_ctx) { }, /* 4*/ { UNICODE_MODE, 2, 32, -1, { { TU("Google Pixel 4a 128 GB Black;price:$439.97"), -1, 3 }, { TU("Google 谷歌 Pixel 4a 128 GB黑色;零售价:¥3149.79"), -1, 29 }, { TU("Google Pixel 4a 128 GB Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 17, 139, 0, "AIM ITS/04-023:2022 Annex A example (shortened); BWIPP different encodation", "1111111010101010101010101011101010101010101010101010101110101010101010101010101010111010101010101010101010101011101010101010101010101010111" - "1000001001000010110111101110110000000110010001001010001010100010000110011100101000101101010100111001001101110110110010000011110000111000101" - "1011101011100111011110110011110001010110001000110011111111110000100000111001000110111011000001100011000000100011101101100100110100110011011" - "1011101001001010011100110110001011111110101111101101000001100101001111110100111010000000011000111101110100000100011001000010001010111100110" - "1011101000001100010010010011011111000001100111100100011100111110001100101010001111111110111000000000101011100001101000001000111100110110111" - "1000001000000011110001010010001001010011011010000100110000111111011101011110010000001100000110101110010111000010001001110111011101111000110" - "1111111010000000010010011101001100101100001010000000000100011111111001000000110011111000111011111010000011011111100111011010000100011000001" - "0000000010011100010100010000111011010000111011111011010010110001100100001000011110000000010001111100010001000000100101100101011000011011110" - "1101110011110000010101110111110111001010010101001110011111101110010110101100100110110100101110100100111100000111111011110100100101011111001" - "0101110111101001110110001110010101111100111101010111000011001111100011011100001001100111001100110101111010101100010101100100010010110101000" - "1000011000101010000011100001100000010101000010001000001100010011011010010000101001110011000011010011011111110101101101101101000101100001001" - "0000110000010010100101011100100001111010010001100100100000101010000111111001110010000101100100111001010001010010011010001110101101111011100" - "1110010111111001100011110101010001100011101010001110101100101100110100100101001101110111101001100111001101111001111010001011111000110111111" - "0100001101110100010111001110101111111010001111100000100010111011000010010110001010000001000001001111000010011100111110010011000111100110001" - "1100011010000101111101101111111111010011001010111001011110010011101010100011101001111010100111010100110100011111110111100101000111010110101" - "1010011110100110011111000010111010001000100111010111011011101000100101110000010011101110110100011010110111010110110011110110000001000110001" + "1000001001000010100111001110100000111100110111111110001010100010000110011100101000101101010100111001001101110110110010000011110000101100101" + "1011101011101011111110110011100101100111101000001011111111110000100000111001000110111011000011100011000000100011101101100100110100110011011" + "1011101001001110000110100100001111011110111110111101000000100101001111110100111010000000011000101101110100000100011001000010001010101111110" + "1011101000010000111010100101101000100010100100110100011110111110001100101010001111110110111000000000101011100001101000001000110000000110111" + "1000001000001001100011001110100010110001011011011100110000111111011101011110010000000000000010001110010111000010001001110111010101011000110" + "1111111010100010010100110101101010100010001110001000100100011111111001000000111011111000110011111010000011011111100111011001000000011010001" + "0000000010010110010000100000000010101010110111110011010010110001100100001000010011000000110101111100010001000000100101100111011000011011110" + "1101110011111001110010000111111111101100100101001110001111101110010110101100001110110110001110100100111100000111111011110100100101011111001" + "0111111100100011001110011010010100110111101101010111000011001111100011011100001100100110011110110101111010101100010101100000010010110101000" + "1011000010101000110000001001010011101001100001111011001100010011011010010000101101110011000011010011011111110101101101100101110101100001001" + "0001110000010011000000110000010111111010010001010100100000101010000111111001110000000101100101110001010001010010011010001110101101111011100" + "1000101101011001001010000001111011100111100000100110101100101100110100100101001101110111101001100111001101111001111010001011011000110111111" + "0110100001110101010110010010100000111110011101011100100010111011000010010110001010000001001001001111000010011100111110010011000110100110001" + "1001000001100110110011100011111101010111100110100101011110010011101010100011101001111010100111010100110100011111110111100101000101010110101" + "1010011110111011011111000010111011001001010001011111011011101000100101110000010011101110110100011010110111010110110011110110000001000110001" "1110101010101010101010101011101010101010101010101010101110101010101010101010101010111010101010101010101010101011101010101010101010101011111" }, /* 5*/ { DATA_MODE, 4, 3, -1, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 7, 77, 1, "Standard example + extra seg, data mode", @@ -8886,6 +8886,7 @@ static void test_fuzz(const testCtx *const p_ctx) { int input_mode; int option_1; int option_2; + int option_3; char *data; int length; int ret; @@ -8894,7 +8895,8 @@ static void test_fuzz(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ struct item data[] = { - /* 0*/ { BARCODE_QRCODE, GS1_MODE | GS1NOCHECK_MODE, -1, -1, "[]CCCCCLLLLLLLLLLLLLLLLLLLLLCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLLLLLLLLLLLLLLLLL000000032861710*383556LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL155816162LLLLLCC%%C%C%%%%%%%%%%%%%%LLLCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLLLLLLLL)!1661055777[723]T5", -1, 0, 1, "" }, /* #300 (#14), Andre Maute */ + /* 0*/ { BARCODE_QRCODE, GS1_MODE | GS1NOCHECK_MODE, -1, -1, -1, "[]CCCCCLLLLLLLLLLLLLLLLLLLLLCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLLLLLLLLLLLLLLLLL000000032861710*383556LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL155816162LLLLLCC%%C%C%%%%%%%%%%%%%%LLLCCCCCCCC%%C%C%%%%%%%%%%%%%%LLLLLLLLLL)!1661055777[723]T5", -1, 0, 1, "" }, /* #300 (#14), Andre Maute */ + /* 1*/ { BARCODE_QRCODE, DATA_MODE, -1, -1, ZINT_FULL_MULTIBYTE, "\215\215\350\2156750\215\215\215\215\215\215\000\000\000\025\215\215\215\215\215\232\215\232\232\001\361\215\215\215\215\215\221\215\215\215\215JJJJJJNJJJJJJ\215\215\215\2159999\215\215\215\215\215\215\215\215\215\235\215\215\215\215\215\035\004\000\000@\000\000\000\000\375\000\000\000\000\000\000\000\000\000\000\000\000\000\241\000\000\000\000\000\000\000\241\247^^^\377\377\377\000 \000\000\000\000\000\000\377\377u\000\000\000\000\000\000\000^\377\377^^\000:\000\177\377\377\377?\377\377\377\377\377\377\377\377\377\377\377\377\377\377\241\241\232\232\232\232\232\232\232\232\000\377\377\377\242\003\000\000\377\377/\000AA\000\000\000\000\000\000\000\000\000\000\000\000T\000\000\000\000\000\000\000\000WWW\237\250WWWWWW\377\377R30 \377\377\000\000\000", 231, 0, 1, "" }, /* #300 (#15), Andre Maute */ }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -8909,7 +8911,7 @@ static void test_fuzz(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, data[i].length, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); diff --git a/docs/manual.html b/docs/manual.html index f13db785..dd3bc5d8 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -196,6 +196,9 @@ padding: 0.125em 0.5em 0.25em 0.5em; vertical-align: top; } + tbody tr:first-child td { + padding-top: 0.5em; + } header { margin-bottom: 4em; text-align: center; @@ -329,7 +332,7 @@

Zint Barcode Generator and Zint Barcode Studio User Manual

Version 2.12.0.9

-

November 2023

+

December 2023