From 6fb0d077bc6067ceec208e13723802f746a9311b Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 14 May 2021 16:04:34 +0100 Subject: [PATCH] EAN14, NVE18: fix checksum calc for zero-filled input --- backend/code128.c | 51 +++++++++++++++--------------------- backend/tests/test_code128.c | 4 +-- backend/tests/test_gs1.c | 24 ++++++++++------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/backend/code128.c b/backend/code128.c index eeeb37d4..933e9377 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -1025,13 +1025,11 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], int len /* Add check digit if encoding an NVE18 symbol */ INTERNAL int nve_18(struct zint_symbol *symbol, unsigned char source[], int length) { - int error_number, zeroes, i, nve_check, total_sum, sourcelen; - unsigned char ean128_equiv[25]; + int i, count, check_digit; + int error_number, zeroes; + unsigned char ean128_equiv[23]; - memset(ean128_equiv, 0, 25); - sourcelen = length; - - if (sourcelen > 17) { + if (length > 17) { strcpy(symbol->errtxt, "345: Input too long"); return ZINT_ERROR_TOO_LONG; } @@ -1041,27 +1039,24 @@ INTERNAL int nve_18(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "346: Invalid characters in data"); return error_number; } - zeroes = 17 - sourcelen; - strcpy((char *) ean128_equiv, "[00]"); + + zeroes = 17 - length; + ustrcpy(ean128_equiv, "[00]"); memset(ean128_equiv + 4, '0', zeroes); - strcpy((char*) ean128_equiv + 4 + zeroes, (char*) source); + ustrcpy(ean128_equiv + 4 + zeroes, source); - total_sum = 0; - for (i = sourcelen - 1; i >= 0; i--) { - total_sum += ctoi(source[i]); - - if (!(i & 1)) { - total_sum += 2 * ctoi(source[i]); - } + count = 0; + for (i = 20; i >= 4; i--) { + count += i & 1 ? ctoi(ean128_equiv[i]) : 3 * ctoi(ean128_equiv[i]); } - nve_check = 10 - total_sum % 10; - if (nve_check == 10) { - nve_check = 0; + check_digit = 10 - count % 10; + if (check_digit == 10) { + check_digit = 0; } - ean128_equiv[21] = itoc(nve_check); + ean128_equiv[21] = itoc(check_digit); ean128_equiv[22] = '\0'; - error_number = ean_128(symbol, ean128_equiv, (int) ustrlen(ean128_equiv)); + error_number = ean_128(symbol, ean128_equiv, 22); return error_number; } @@ -1070,7 +1065,7 @@ INTERNAL int nve_18(struct zint_symbol *symbol, unsigned char source[], int leng INTERNAL int ean_14(struct zint_symbol *symbol, unsigned char source[], int length) { int i, count, check_digit; int error_number, zeroes; - unsigned char ean128_equiv[20]; + unsigned char ean128_equiv[19]; if (length > 13) { strcpy(symbol->errtxt, "347: Input wrong length"); @@ -1084,17 +1079,13 @@ INTERNAL int ean_14(struct zint_symbol *symbol, unsigned char source[], int leng } zeroes = 13 - length; - strcpy((char*) ean128_equiv, "[01]"); + ustrcpy(ean128_equiv, "[01]"); memset(ean128_equiv + 4, '0', zeroes); ustrcpy(ean128_equiv + 4 + zeroes, source); count = 0; - for (i = length - 1; i >= 0; i--) { - count += ctoi(source[i]); - - if (!(i & 1)) { - count += 2 * ctoi(source[i]); - } + for (i = 16; i >= 4; i--) { + count += i & 1 ? ctoi(ean128_equiv[i]) : 3 * ctoi(ean128_equiv[i]); } check_digit = 10 - (count % 10); if (check_digit == 10) { @@ -1103,7 +1094,7 @@ INTERNAL int ean_14(struct zint_symbol *symbol, unsigned char source[], int leng ean128_equiv[17] = itoc(check_digit); ean128_equiv[18] = '\0'; - error_number = ean_128(symbol, ean128_equiv, (int) ustrlen(ean128_equiv)); + error_number = ean_128(symbol, ean128_equiv, 18); return error_number; } diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index 27ebcb14..eeb8ff3e 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -228,8 +228,8 @@ static void test_reader_init(int index, int generate, int debug) { /* 1*/ { BARCODE_CODE128, UNICODE_MODE, READER_INIT, "12", 0, 1, 68, "(6) 104 96 99 12 22 106", "StartB FNC3 CodeC 12" }, /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, READER_INIT, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, /* 3*/ { BARCODE_GS1_128, GS1_MODE, READER_INIT, "[90]12", 0, 1, 68, "(6) 105 102 90 12 11 106", "StartC FNC1 90 12 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, - /* 4*/ { BARCODE_EAN14, GS1_MODE, READER_INIT, "12", ZINT_WARN_NONCOMPLIANT, 1, 134, "Warning (12) 105 102 1 0 0 0 0 0 1 25 30 106", "StartC FNC1 01 00 (5) 01 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, - /* 5*/ { BARCODE_NVE18, GS1_MODE, READER_INIT, "12", ZINT_WARN_NONCOMPLIANT, 1, 156, "Warning (14) 105 102 0 0 0 0 0 0 0 0 1 25 80 106", "StartC FNC1 00 (8) 01 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, + /* 4*/ { BARCODE_EAN14, GS1_MODE, READER_INIT, "12", 0, 1, 134, "(12) 105 102 1 0 0 0 0 0 1 23 12 106", "StartC FNC1 01 00 (5) 01 23 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, + /* 5*/ { BARCODE_NVE18, GS1_MODE, READER_INIT, "12", 0, 1, 156, "(14) 105 102 0 0 0 0 0 0 0 0 1 23 58 106", "StartC FNC1 00 (8) 01 23 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, /* 6*/ { BARCODE_HIBC_128, UNICODE_MODE, READER_INIT, "A", 0, 1, 79, "(7) 104 96 11 33 24 5 106", "StartA FNC3 + A 8 (check) (Not sensible, use CODE128)" }, }; int data_size = ARRAY_SIZE(data); diff --git a/backend/tests/test_gs1.c b/backend/tests/test_gs1.c index ca515ee5..b4abba29 100644 --- a/backend/tests/test_gs1.c +++ b/backend/tests/test_gs1.c @@ -244,15 +244,21 @@ static void test_hrt(int index, int debug) { /* 2*/ { BARCODE_GS1_128_CC, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* 3*/ { BARCODE_GS1_128_CC, "[01]12345678901231[20]12", "[21]12345", 0, "(01)12345678901231(20)12" }, /* 4*/ { BARCODE_EAN14, "1234567890123", "", 0, "(01)12345678901231" }, - /* 5*/ { BARCODE_NVE18, "12345678901234567", "", 0, "(00)123456789012345675" }, - /* 6*/ { BARCODE_DBAR_EXP, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, - /* 7*/ { BARCODE_DBAR_EXP, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, - /* 8*/ { BARCODE_DBAR_EXP_CC, "[01]12345678901234", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234" }, - /* 9*/ { BARCODE_DBAR_EXP_CC, "[01]12345678901231", "[21]12345", 0, "(01)12345678901231" }, - /* 10*/ { BARCODE_DBAR_EXPSTK, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "" }, - /* 11*/ { BARCODE_DBAR_EXPSTK, "[01]12345678901231[20]12", "", 0, "" }, - /* 12*/ { BARCODE_DBAR_EXPSTK_CC, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "" }, - /* 13*/ { BARCODE_DBAR_EXPSTK_CC, "[01]12345678901231[20]12", "[21]12345", 0, "" }, + /* 5*/ { BARCODE_EAN14, "1234", "", 0, "(01)00000000012348" }, + /* 6*/ { BARCODE_EAN14, "12345", "", 0, "(01)00000000123457" }, + /* 7*/ { BARCODE_EAN14, "12340", "", 0, "(01)00000000123402" }, + /* 8*/ { BARCODE_NVE18, "12345678901234567", "", 0, "(00)123456789012345675" }, + /* 9*/ { BARCODE_NVE18, "1234", "", 0, "(00)000000000000012348" }, + /* 10*/ { BARCODE_NVE18, "12345", "", 0, "(00)000000000000123457" }, + /* 11*/ { BARCODE_NVE18, "12340", "", 0, "(00)000000000000123402" }, + /* 12*/ { BARCODE_DBAR_EXP, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, + /* 13*/ { BARCODE_DBAR_EXP, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, + /* 14*/ { BARCODE_DBAR_EXP_CC, "[01]12345678901234", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234" }, + /* 15*/ { BARCODE_DBAR_EXP_CC, "[01]12345678901231", "[21]12345", 0, "(01)12345678901231" }, + /* 16*/ { BARCODE_DBAR_EXPSTK, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "" }, + /* 17*/ { BARCODE_DBAR_EXPSTK, "[01]12345678901231[20]12", "", 0, "" }, + /* 18*/ { BARCODE_DBAR_EXPSTK_CC, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "" }, + /* 19*/ { BARCODE_DBAR_EXPSTK_CC, "[01]12345678901231[20]12", "[21]12345", 0, "" }, }; int data_size = ARRAY_SIZE(data);