From b3610d3c43a4f57e9d487ae5796c16829aaa56e0 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 9 Feb 2021 02:51:36 +0000 Subject: [PATCH] #209 font.h guard; improve gs1 c82 check, code1 num_digits --- backend/code1.c | 77 ++++++++++++++++++++++++------------------------- backend/font.h | 7 ++++- backend/gs1.c | 42 +++++++++++++-------------- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/backend/code1.c b/backend/code1.c index 0b1220d3..8a0f911e 100644 --- a/backend/code1.c +++ b/backend/code1.c @@ -311,20 +311,14 @@ static int is_last_single_ascii(const unsigned char string[], const int length, return 0; } -/* Return length of numeric sequence from position `sp`, stopping after `max` if given (non-zero) */ -static int digits_ahead(const unsigned char string[], const int length, const int sp, const int max) { - int i, end; - if (max && sp + max < length) { - end = sp + max; - } else { - end = length; - } - for (i = sp; i < end; i++) { - if (string[i] < '0' || string[i] > '9') { - break; +/* Initialize number of digits array (taken from BWIPP) */ +static void set_num_digits(const unsigned char source[], const int length, int *num_digits) { + int i; + for (i = length - 1; i >= 0; i--) { + if (source[i] >= '0' && source[i] <= '9') { + num_digits[i] = num_digits[i + 1] + 1; } } - return i - sp; } /* Copy C40/TEXT/EDI triplets from buffer to target. Returns elements left in buffer (< 3) */ @@ -414,7 +408,7 @@ static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int targe } /* Number of codewords remaining in a particular version (may be negative) */ -static int codewords_remaining(struct zint_symbol *symbol, int tp) { +static int codewords_remaining(struct zint_symbol *symbol, const int tp) { int i; if (symbol->option_2 == 10) { /* Version T */ @@ -455,7 +449,8 @@ static int c40text_cnt(const int current_mode, const int gs1, unsigned char inpu } /* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */ -static void eci_escape(const int eci, unsigned char *source, const int length, unsigned char *eci_buf, const int eci_length) { +static void eci_escape(const int eci, unsigned char *source, const int length, unsigned char *eci_buf, + const int eci_length) { int i, j; j = sprintf((char *) eci_buf, "\\%06d", eci); @@ -482,12 +477,15 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne int eci_length = length + 7 + chr_cnt(source, length, '\\'); #ifndef _MSC_VER unsigned char eci_buf[eci_length + 1]; + int num_digits[eci_length + 1]; #else unsigned char *eci_buf = (unsigned char *) _alloca(eci_length + 1); + int *num_digits = (int *) _alloca(sizeof(int) * (eci_length + 1)); #endif sp = 0; tp = 0; + memset(num_digits, 0, sizeof(int) * (eci_length + 1)); /* Step A */ current_mode = C1_ASCII; @@ -499,22 +497,26 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne gs1 = 0; } if (gs1) { - if (length >= 15 && digits_ahead(source, length, 0, 15) == 15) { + set_num_digits(source, length, num_digits); + if (length >= 15 && num_digits[0] >= 15) { target[tp++] = 236; /* FNC1 and change to Decimal */ next_mode = C1_DECIMAL; - } else if (length >= 7 && digits_ahead(source, length, 0, 0) == length) { + } else if (length >= 7 && num_digits[0] == length) { target[tp++] = 236; /* FNC1 and change to Decimal */ next_mode = C1_DECIMAL; } else { target[tp++] = 232; /* FNC1 */ } /* Note ignoring ECI if GS1 mode (up to caller to warn) */ - } else if (symbol->eci) { - target[tp++] = 129; /* Pad */ - target[tp++] = '\\' + 1; /* Escape char */ - eci_escape(symbol->eci, source, length, eci_buf, eci_length); - source = eci_buf; - length = eci_length; + } else { + if (symbol->eci) { + target[tp++] = 129; /* Pad */ + target[tp++] = '\\' + 1; /* Escape char */ + eci_escape(symbol->eci, source, length, eci_buf, eci_length); + source = eci_buf; + length = eci_length; + } + set_num_digits(source, length, num_digits); } do { @@ -539,11 +541,11 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne /* Step B - ASCII encodation */ next_mode = C1_ASCII; - if ((length - sp) >= 21 && digits_ahead(source, length, sp, 21) == 21) { + if ((length - sp) >= 21 && num_digits[sp] >= 21) { /* Step B1 */ next_mode = C1_DECIMAL; db_p = bin_append_posn(15, 4, decimal_binary, db_p); - } else if ((length - sp) >= 13 && digits_ahead(source, length, sp, 0) == (length - sp)) { + } else if ((length - sp) >= 13 && num_digits[sp] == (length - sp)) { /* Step B2 */ next_mode = C1_DECIMAL; db_p = bin_append_posn(15, 4, decimal_binary, db_p); @@ -558,12 +560,12 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne sp += 2; } else { if ((gs1) && (source[sp] == '[')) { - if (length - (sp + 1) >= 15 && digits_ahead(source, length, sp + 1, 15) == 15) { + if (length - (sp + 1) >= 15 && num_digits[sp + 1] >= 15) { /* Step B4 */ target[tp++] = 236; /* FNC1 and change to Decimal */ sp++; next_mode = C1_DECIMAL; - } else if (length - (sp + 1) >= 7 && digits_ahead(source, length, sp + 1, 0) == length - (sp + 1)) { + } else if (length - (sp + 1) >= 7 && num_digits[sp + 1] == length - (sp + 1)) { /* Step B5 */ target[tp++] = 236; /* FNC1 and change to Decimal */ sp++; @@ -602,10 +604,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne next_mode = current_mode; if (cte_p == 0) { /* Step C/D1 */ - if ((length - sp) >= 12 && digits_ahead(source, length, sp, 12) == 12) { + if ((length - sp) >= 12 && num_digits[sp] >= 12) { /* Step C/D1a */ next_mode = C1_ASCII; - } else if ((length - sp) >= 8 && digits_ahead(source, length, sp, 0) == (length - sp)) { + } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) { /* Step C/D1b */ next_mode = C1_ASCII; } else { @@ -658,10 +660,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne next_mode = C1_EDI; if (cte_p == 0) { /* Step E1 */ - if ((length - sp) >= 12 && digits_ahead(source, length, sp, 12) == 12) { + if ((length - sp) >= 12 && num_digits[sp] >= 12) { /* Step E1a */ next_mode = C1_ASCII; - } else if ((length - sp) >= 8 && digits_ahead(source, length, sp, 0) == (length - sp)) { + } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) { /* Step E1b */ next_mode = C1_ASCII; } else if ((length - sp) < 3 || !isedi(source[sp]) || !isedi(source[sp + 1]) @@ -700,20 +702,17 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } else if (current_mode == C1_DECIMAL) { /* Step F - Decimal encodation */ - int decimal_count; if (debug_print) printf("DECIMAL "); next_mode = C1_DECIMAL; - decimal_count = digits_ahead(source, length, sp, 3); - if (length - sp < 3) { /* Step F1 */ int bits_left = 8 - db_p; - int single_ascii = bits_left == 8 && is_last_single_ascii(source, length, sp); - if (codewords_remaining(symbol, tp) == 1 && (single_ascii || (decimal_count == 1 && bits_left >= 4))) { - if (single_ascii) { + int can_ascii = bits_left == 8 && is_last_single_ascii(source, length, sp); + if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { + if (can_ascii) { /* Encode last character or last 2 digits as ASCII */ if (istwodigits(source, length, sp)) { target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; @@ -732,15 +731,15 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp); } } else { - db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, decimal_count, source, &sp); + db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); current_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ } next_mode = C1_ASCII; } else { - if (decimal_count != 3) { + if (num_digits[sp] < 3) { /* Step F2 */ - db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, decimal_count, source, &sp); + db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); current_mode = next_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ } else { /* Step F3 */ diff --git a/backend/font.h b/backend/font.h index d4c3ced9..a01abaf7 100644 --- a/backend/font.h +++ b/backend/font.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008 - 2020 Robin Stuart + Copyright (C) 2008 - 2021 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -31,6 +31,9 @@ */ /* vim: set ts=4 sw=4 et : */ +#ifndef FONT_H +#define FONT_H + typedef const unsigned short font_item; #define NORMAL_FONT_WIDTH 7 @@ -482,3 +485,5 @@ static font_item upcean_small_font[] = { /*38*/ 0x3C, 0x7E, 0x66, 0x42, 0x66, 0x3C, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0x7E, 0x3C, /* 8 */ /*39*/ 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xE3, 0x7E, 0x1E, 0x0C, 0x18, 0x30, 0x60, /* 9 */ }; + +#endif /* FONT_H */ diff --git a/backend/gs1.c b/backend/gs1.c index 2dc1d13a..3d5ea293 100644 --- a/backend/gs1.c +++ b/backend/gs1.c @@ -67,13 +67,21 @@ static int numeric(const unsigned char *data, int data_len, int offset, int min, return 1; } -/* Validate of character set 82 (GS1 General Spec Figure 7.11-1) */ +/* GS1 General Specifications 21.0.1 Figure 7.9.5-1. GS1 AI encodable character reference values. + Also used to determine if character in set 82 */ +static const char c82[] = { + 0, 1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /*!-0*/ + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, /*1-@*/ + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, /*A-P*/ + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -1, -1, -1, -1, 55, -1, /*Q-`*/ + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /*a-p*/ + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /*q-z*/ +}; + +/* Validate of character set 82 (GS1 General Specifications Figure 7.11-1) */ static int cset82(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50]) { - /* These 13 characters plus all <= ' ' = 13 + 33 = 46 + 82 = 128 */ - static const char not_in_set82[] = "#$@[\\]^`{|}~\177"; - data_len -= offset; if (data_len < min) { @@ -85,7 +93,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min, const unsigned char *de = d + (data_len > max ? max : data_len); for (; d < de; d++) { - if (*d <= ' ' || strchr(not_in_set82, *d) != NULL) { + if (*d < '!' || *d > 'z' || c82[*d - '!'] == -1) { *p_err_no = 3; *p_err_posn = d - data + 1; sprintf(err_msg, "Invalid CSET 82 character '%c'", *d); @@ -97,7 +105,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min, return 1; } -/* Validate of character set 39 (GS1 General Spec Figure 7.11-2) */ +/* Validate of character set 39 (GS1 General Specifications Figure 7.11-2) */ static int cset39(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50]) { @@ -125,7 +133,7 @@ static int cset39(const unsigned char *data, int data_len, int offset, int min, return 1; } -/* Check a check digit (GS1 General Spec 7.9.1) */ +/* Check a check digit (GS1 General Specifications 7.9.1) */ static int csum(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { @@ -160,7 +168,7 @@ static int csum(const unsigned char *data, int data_len, int offset, int min, in return 1; } -/* Check alphanumeric check characters (GS1 General Spec 7.9.5) */ +/* Check alphanumeric check characters (GS1 General Specifications 7.9.5) */ static int csumalpha(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { (void)max; @@ -176,14 +184,6 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi } if (!length_only && data_len) { - static const char c82[] = { - 0, 1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /*!-0*/ - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, /*1-@*/ - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, /*A-P*/ - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -1, -1, -1, -1, 55, -1, /*Q-`*/ - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /*a-p*/ - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /*q-z*/ - }; static const char c32[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; static const char weights[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83 @@ -215,7 +215,7 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi return 1; } -/* Check for a GS1 Prefix (GS1 General Spec GS1 1.4.2) */ +/* Check for a GS1 Prefix (GS1 General Specifications GS1 1.4.2) */ static int key(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { (void)max; @@ -278,7 +278,7 @@ static int yymmd0(const unsigned char *data, int data_len, int offset, int min, } if (month == 2 && day == 29) { /* Leap year check */ int year = to_int(data + offset, 2); - if (year & 3) { /* Good until 2050 when 00 will mean 2100 (GS1 General Spec 7.12) */ + if (year & 3) { /* Good until 2050 when 00 will mean 2100 (GS1 General Specifications 7.12) */ *p_err_no = 3; *p_err_posn = offset + 4 + 1; sprintf(err_msg, "Invalid day '%.2s'", data + offset + 4); @@ -595,7 +595,7 @@ static int yesno(const unsigned char *data, int data_len, int offset, int min, i return 1; } -/* Check for importer index (GS1 General Spec 3.8.17) */ +/* Check for importer index (GS1 General Specifications 3.8.17) */ static int importeridx(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { (void)max; @@ -645,7 +645,7 @@ static int nonzero(const unsigned char *data, int data_len, int offset, int min, return 1; } -/* Check winding direction (0/1/9) (GS1 General Spec 3.9.1) */ +/* Check winding direction (0/1/9) (GS1 General Specifications 3.9.1) */ static int winding(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { (void)max; @@ -691,7 +691,7 @@ static int zero(const unsigned char *data, int data_len, int offset, int min, in return 1; } -/* Check piece of a trade item (GS1 General Spec 3.9.6 and 3.9.17) */ +/* Check piece of a trade item (GS1 General Specifications 3.9.6 and 3.9.17) */ static int pieceoftotal(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50], const int length_only) { (void)max;