diff --git a/CMakeLists.txt b/CMakeLists.txt index f040d870..a48c7b1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ add_definitions (-DZINT_VERSION=\"${ZINT_VERSION}\" -Wall) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ) +set(ZINT_DEBUG FALSE CACHE BOOL "Set debug compile flag") +set(ZINT_SANITIZE FALSE CACHE BOOL "Set sanitize compile/link flags") + include (SetPaths.cmake) INCLUDE (CheckCXXCompilerFlag) @@ -26,6 +29,15 @@ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) if (CXX_COMPILER_FLAG_WALL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif (CXX_COMPILER_FLAG_WALL) + if (ZINT_DEBUG) + add_compile_options("-g") + add_compile_options("-O0") + endif (ZINT_DEBUG) + if (ZINT_SANITIZE) + add_compile_options("-fsanitize=undefined") + add_compile_options("-fsanitize=address") + set (CMAKE_EXE_LINKER_FLAGS "-fsanitize=undefined -fsanitize=address") + endif (ZINT_SANITIZE) endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) diff --git a/backend/code.c b/backend/code.c index 0ca5dee5..ede641f4 100644 --- a/backend/code.c +++ b/backend/code.c @@ -582,6 +582,9 @@ int channel_code(struct zint_symbol *symbol, unsigned char source[], int length) NextS(channels, 3, channels, channels); zeroes = channels - 1 - length; + if (zeroes < 0) { + zeroes = 0; + } memset(hrt, '0', zeroes); strcpy(hrt + zeroes, (char *) source); ustrcpy(symbol->text, (unsigned char *) hrt); diff --git a/backend/eci.c b/backend/eci.c index b8098356..22b6b0f7 100644 --- a/backend/eci.c +++ b/backend/eci.c @@ -46,11 +46,9 @@ int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[] int done; if (eci == 26) { - int in_length = (int) *length; /* Unicode mode, do not process - just copy data across */ - for (in_posn = 0; in_posn < in_length; in_posn++) { - dest[in_posn] = source[in_posn]; - } + memcpy(dest, source, *length); + dest[*length] = '\0'; return 0; } @@ -107,42 +105,8 @@ int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[] glyph += (source[in_posn + 2] & 0x3f); } - if ((source[in_posn] >= 0xf0) && (source[in_posn] < 0xf7)) { - /* Four-byte character */ - bytelen = 4; - glyph = (source[in_posn] & 0x07) << 18; - - if (*length < (in_posn + 2)) { - return ZINT_ERROR_INVALID_DATA; - } - - if (*length < (in_posn + 3)) { - return ZINT_ERROR_INVALID_DATA; - } - - if (*length < (in_posn + 4)) { - return ZINT_ERROR_INVALID_DATA; - } - - if (source[in_posn + 1] > 0xc0) { - return ZINT_ERROR_INVALID_DATA; - } - - if (source[in_posn + 2] > 0xc0) { - return ZINT_ERROR_INVALID_DATA; - } - - if (source[in_posn + 3] > 0xc0) { - return ZINT_ERROR_INVALID_DATA; - } - - glyph += (source[in_posn + 1] & 0x3f) << 12; - glyph += (source[in_posn + 2] & 0x3f) << 6; - glyph += (source[in_posn + 3] & 0x3f); - } - - if (source[in_posn] >= 0xf7) { - /* More than 4 bytes not supported */ + if (source[in_posn] >= 0xf0 || glyph > 0x2122) { + /* Not in any ISO 8859 or Windows page */ return ZINT_ERROR_INVALID_DATA; } @@ -269,6 +233,9 @@ int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[] default: break; } + if (done) { + break; + } } if (!(done)) { diff --git a/backend/eci.h b/backend/eci.h index 54c48f87..d4f2534c 100644 --- a/backend/eci.h +++ b/backend/eci.h @@ -196,6 +196,7 @@ static const unsigned short int iso_8859_16[] = {// Latin alphabet No. 10 0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b, 0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c, 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a, 0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff }; diff --git a/backend/imail.c b/backend/imail.c index fe60215a..09f41c8d 100644 --- a/backend/imail.c +++ b/backend/imail.c @@ -254,6 +254,7 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { int codeword[10]; unsigned short characters[10]; short int bar_map[130]; + int zip_len; error_number = 0; @@ -301,7 +302,13 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { strcpy(symbol->errtxt, "452: Invalid length tracking code"); return ZINT_ERROR_INVALID_DATA; } - if (strlen(zip) > 11) { + if (tracker[1] > '4') { + strcpy(symbol->errtxt, "454: Invalid Barcode Identifier"); + return ZINT_ERROR_INVALID_DATA; + } + + zip_len = strlen(zip); + if (zip_len != 0 && zip_len != 5 && zip_len != 9 && zip_len != 11) { strcpy(symbol->errtxt, "453: Invalid ZIP code"); return ZINT_ERROR_INVALID_DATA; } @@ -314,7 +321,7 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { accum[i] = 0; } - for (read = 0; read < strlen(zip); read++) { + for (read = 0; read < zip_len; read++) { binary_multiply(accum, "10"); binary_load(x_reg, "0", 1); @@ -332,13 +339,13 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { x_reg[i] = accum[i]; } - if (strlen(zip) > 9) { + if (zip_len > 9) { strcpy(zip_adder, "1000100001"); } else { - if (strlen(zip) > 5) { + if (zip_len > 5) { strcpy(zip_adder, "100001"); } else { - if (strlen(zip) > 0) { + if (zip_len > 0) { strcpy(zip_adder, "1"); } else { strcpy(zip_adder, "0"); @@ -439,7 +446,7 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { x_reg[94] = 1; for (i = 92; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } @@ -465,7 +472,7 @@ int imail(struct zint_symbol *symbol, unsigned char source[], int length) { x_reg[93] = 1; x_reg[91] = 1; for (i = 91; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } diff --git a/backend/large.c b/backend/large.c index 0f574e34..32e7e287 100644 --- a/backend/large.c +++ b/backend/large.c @@ -173,7 +173,7 @@ short int islarger(short int accum[], short int reg[]) { latch = 1; } i--; - } while ((latch == 0) && (i >= -1)); + } while ((latch == 0) && (i >= 0)); return larger; } diff --git a/backend/library.c b/backend/library.c index e4b33f16..82d5ff4c 100644 --- a/backend/library.c +++ b/backend/library.c @@ -917,10 +917,10 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int #endif error_number = 0; - if (in_length == 0) { + if (in_length <= 0) { in_length = (int)ustrlen(source); } - if (in_length == 0) { + if (in_length <= 0) { strcpy(symbol->errtxt, "205: No input data"); error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); return ZINT_ERROR_INVALID_DATA; @@ -977,9 +977,6 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if (symbol->symbology == 36) { symbol->symbology = BARCODE_UPCA; } - if (symbol->symbology == 38) { - symbol->symbology = BARCODE_UPCE; - } if ((symbol->symbology >= 41) && (symbol->symbology <= 45)) { symbol->symbology = BARCODE_POSTNET; } @@ -1157,8 +1154,23 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int case BARCODE_MICROQR: case BARCODE_GRIDMATRIX: case BARCODE_HANXIN: - error_number = utf_to_eci(symbol->eci, source, local_source, (size_t*)&in_length); - error_number = extended_charset(symbol, local_source, in_length); + { +#ifndef _MSC_VER + unsigned char temp[in_length + 1]; +#else + unsigned char *temp = (unsigned char*) _alloca(in_length + 1); +#endif + size_t temp_len = in_length; + memcpy(temp, local_source, temp_len); + temp[temp_len] = '\0'; + error_number = utf_to_eci(symbol->eci, local_source, temp, &temp_len); + if (error_number == 0) { + in_length = (int) temp_len; + memcpy(local_source, temp, in_length); + local_source[in_length] = '\0'; + error_number = extended_charset(symbol, local_source, in_length); + } + } break; default: error_number = reduced_charset(symbol, local_source, in_length); diff --git a/backend/mailmark.c b/backend/mailmark.c index 05ba9d5a..0aebc22d 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -464,14 +464,14 @@ int mailmark(struct zint_symbol *symbol, const unsigned char source[], const siz } a[96] = 1; for (i = 91; i >= 0; i--) { - b[i] = islarger(cdv, a); + b[i] = !islarger(a, cdv); if (b[i] == 1) { binary_subtract(cdv, a); } shiftdown(a); } - data[j] = (cdv[5] * 32) + (cdv[4] * 16) + (cdv[3] * 8) + (cdv[2] * 4) + + data[j] = (cdv[4] * 16) + (cdv[3] * 8) + (cdv[2] * 4) + (cdv[1] * 2) + cdv[0]; } @@ -486,14 +486,14 @@ int mailmark(struct zint_symbol *symbol, const unsigned char source[], const siz a[93] = 1; a[92] = 1; for (i = 91; i >= 0; i--) { - b[i] = islarger(cdv, a); + b[i] = !islarger(a, cdv); if (b[i] == 1) { binary_subtract(cdv, a); } shiftdown(a); } - data[j] = (cdv[5] * 32) + (cdv[4] * 16) + (cdv[3] * 8) + (cdv[2] * 4) + + data[j] = (cdv[4] * 16) + (cdv[3] * 8) + (cdv[2] * 4) + (cdv[1] * 2) + cdv[0]; } diff --git a/backend/maxicode.c b/backend/maxicode.c index 2401fb1f..c8bd802d 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -367,8 +367,8 @@ int maxi_text_process(int mode, unsigned char source[], int length, int eci) { } break; case 3: - if (i + 3 < 144 && set[i + 1] == 3 && set[i + 2] == 3 && set[i + 3] == 3) { - maxi_bump(set, character, i); + if (i + 3 < 144 && set[i + 1] == 3 && set[i + 2] == 3 && set[i + 3] == 3) { + maxi_bump(set, character, i); character[i] = 60; maxi_bump(set, character, i); character[i] = 60; @@ -389,7 +389,7 @@ int maxi_text_process(int mode, unsigned char source[], int length, int eci) { character[i] = 61; maxi_bump(set, character, i); character[i] = 61; - current_set = 3; + current_set = 4; length++; i += 3; } else { @@ -405,7 +405,7 @@ int maxi_text_process(int mode, unsigned char source[], int length, int eci) { character[i] = 62; maxi_bump(set, character, i); character[i] = 62; - current_set = 3; + current_set = 5; length++; i += 3; } else { diff --git a/backend/rss.c b/backend/rss.c index 527847d2..6acac02e 100644 --- a/backend/rss.c +++ b/backend/rss.c @@ -221,7 +221,7 @@ int rss14(struct zint_symbol *symbol, unsigned char source[], int src_len) { } for (i = 24; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } @@ -245,7 +245,7 @@ int rss14(struct zint_symbol *symbol, unsigned char source[], int src_len) { } for (i = 24; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } @@ -275,7 +275,7 @@ int rss14(struct zint_symbol *symbol, unsigned char source[], int src_len) { } for (i = 24; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } @@ -790,7 +790,7 @@ int rsslimited(struct zint_symbol *symbol, unsigned char source[], int src_len) } for (i = 24; i >= 0; i--) { - y_reg[i] = islarger(accum, x_reg); + y_reg[i] = !islarger(x_reg, accum); if (y_reg[i] == 1) { binary_subtract(accum, x_reg); } diff --git a/backend/upcean.c b/backend/upcean.c index 6701a2ab..d93eec06 100644 --- a/backend/upcean.c +++ b/backend/upcean.c @@ -138,7 +138,7 @@ int upca(struct zint_symbol *symbol, unsigned char source[], char dest[]) { gtin[length - 1] = '\0'; if (source[length - 1] != upc_check(gtin)) { strcpy(symbol->errtxt, "270: Invalid check digit"); - return ZINT_ERROR_INVALID_DATA; + return ZINT_ERROR_INVALID_CHECK; } gtin[length - 1] = upc_check(gtin); } @@ -150,7 +150,7 @@ int upca(struct zint_symbol *symbol, unsigned char source[], char dest[]) { /* UPC E is a zero-compressed version of UPC A */ int upce(struct zint_symbol *symbol, unsigned char source[], char dest[]) { unsigned int i, num_system; - char emode, equivalent[12], check_digit, parity[8], temp[8]; + char emode, equivalent[12], check_digit, parity[8], temp[9]; char hrt[9]; /* Two number systems can be used - system 0 and system 1 */ @@ -191,7 +191,7 @@ int upce(struct zint_symbol *symbol, unsigned char source[], char dest[]) { } strcpy(temp, (char*) source); strcpy(hrt, (char*) source); - for (i = 1; i <= 7; i++) { + for (i = 1; i <= 8; i++) { source[i - 1] = temp[i]; } } else { @@ -294,7 +294,7 @@ int upce(struct zint_symbol *symbol, unsigned char source[], char dest[]) { } else { if (hrt[7] != check_digit) { strcpy(symbol->errtxt, "274: Invalid check digit"); - return ZINT_ERROR_INVALID_DATA; + return ZINT_ERROR_INVALID_CHECK; } } ustrcpy(symbol->text, (unsigned char*) hrt); @@ -517,7 +517,7 @@ static int isbn(struct zint_symbol *symbol, unsigned char source[], const size_t } /* Input must be 9, 10 or 13 characters */ - if (((src_len < 9) || (src_len > 13)) || ((src_len > 10) && (src_len < 13))) { + if (src_len != 9 && src_len != 10 && src_len != 13) { strcpy(symbol->errtxt, "278: Input wrong length"); return ZINT_ERROR_TOO_LONG; } @@ -535,25 +535,6 @@ static int isbn(struct zint_symbol *symbol, unsigned char source[], const size_t return ZINT_ERROR_INVALID_CHECK; } source[12] = '\0'; - - ean13(symbol, source, dest); - } - - if (src_len == 10) /* Using 10 digit ISBN */ { - check_digit = isbn_check(source); - if (check_digit != source[src_len - 1]) { - strcpy(symbol->errtxt, "281: Incorrect ISBN check"); - return ZINT_ERROR_INVALID_CHECK; - } - for (i = 13; i > 0; i--) { - source[i] = source[i - 3]; - } - source[0] = '9'; - source[1] = '7'; - source[2] = '8'; - source[12] = '\0'; - - ean13(symbol, source, dest); } if (src_len == 9) /* Using 9 digit SBN */ { @@ -562,27 +543,24 @@ static int isbn(struct zint_symbol *symbol, unsigned char source[], const size_t source[i] = source[i - 1]; } source[0] = '0'; + } - /* Verify check digit */ + if (src_len == 9 || src_len == 10) /* Using 10 digit ISBN or 9 digit SBN padded with leading zero */ { check_digit = isbn_check(source); if (check_digit != source[ustrlen(source) - 1]) { - strcpy(symbol->errtxt, "282: Incorrect SBN check"); + strcpy(symbol->errtxt, src_len == 9 ? "281: Incorrect SBN check" : "281: Incorrect ISBN check"); return ZINT_ERROR_INVALID_CHECK; } - - /* Convert to EAN-13 number */ - for (i = 13; i > 0; i--) { + for (i = 11; i > 2; i--) { source[i] = source[i - 3]; } source[0] = '9'; source[1] = '7'; source[2] = '8'; source[12] = '\0'; - - ean13(symbol, source, dest); } - return 0; + return ean13(symbol, source, dest); } /* Add leading zeroes to EAN and UPC strings */ @@ -862,7 +840,7 @@ int eanx(struct zint_symbol *symbol, unsigned char source[], int src_len) { break; case BARCODE_UPCE: case BARCODE_UPCE_CHK: - if ((ustrlen(first_part) >= 6) && (ustrlen(first_part) <= 8)) { + if ((ustrlen(first_part) >= 6) && (ustrlen(first_part) <= (symbol->symbology == BARCODE_UPCE ? 7 : 8))) { error_number = upce(symbol, first_part, (char*) dest); } else { strcpy(symbol->errtxt, "290: Input wrong length");