library: strip_bom: copy NUL; error_tag: defensively truncate, return error

This commit is contained in:
gitlost 2021-01-12 19:51:54 +00:00
parent e1e0aa7ac4
commit b999c11414
2 changed files with 262 additions and 163 deletions

View File

@ -191,20 +191,17 @@ INTERNAL int dpd_parcel(struct zint_symbol *symbol, unsigned char source[], int
INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */
static void error_tag(char error_string[], int error_number) {
STATIC_UNLESS_ZINT_TEST int error_tag(char error_string[100], int error_number) {
if (error_number != 0) {
const char *fmt = error_number >= ZINT_ERROR ? "Error %.93s" : "Warning %.91s"; /* Truncate if too long */
char error_buffer[100];
strcpy(error_buffer, error_string);
if (error_number >= ZINT_ERROR) {
strcpy(error_string, "Error ");
} else {
strcpy(error_string, "Warning ");
sprintf(error_string, fmt, error_buffer);
}
strcat(error_string, error_buffer);
}
return error_number;
}
/* Output a hexadecimal representation of the rendered symbol */
@ -931,19 +928,18 @@ static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, in
return error_number;
}
static void strip_bom(unsigned char *source, int *input_length) {
STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length) {
int i;
if (*input_length > 3) {
if((source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) {
/* Note if BOM is only data then not stripped */
if (*input_length > 3 && (source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) {
/* BOM at start of input data, strip in accordance with RFC 3629 */
for (i = 3; i < *input_length; i++) {
for (i = 3; i <= *input_length; i++) { /* Include terminating NUL */
source[i - 3] = source[i];
}
*input_length -= 3;
}
}
}
static int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string, int *length) {
int error_number;
@ -1077,7 +1073,7 @@ static int escape_char_process(struct zint_symbol *symbol, unsigned char *input_
}
/* Is string valid UTF-8? */
static int is_valid_utf8(const unsigned char source[], const int length) {
STATIC_UNLESS_ZINT_TEST int is_valid_utf8(const unsigned char source[], const int length) {
int i;
unsigned int codepoint, state = 0;
@ -1091,7 +1087,7 @@ static int is_valid_utf8(const unsigned char source[], const int length) {
}
int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int in_length) {
int error_number, error_buffer;
int error_number, warn_number;
#ifdef _MSC_VER
unsigned char *local_source;
#endif
@ -1107,25 +1103,22 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
source, symbol->primary);
}
error_number = 0;
warn_number = 0;
if (source == NULL) {
strcpy(symbol->errtxt, "200: Input data NULL");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
if (in_length <= 0) {
in_length = (int) ustrlen(source);
}
if (in_length <= 0) {
strcpy(symbol->errtxt, "205: No input data");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
if (in_length > ZINT_MAX_DATA_LEN) {
strcpy(symbol->errtxt, "243: Input data too long");
error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG);
return ZINT_ERROR_TOO_LONG;
return error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG);
}
if (*symbol->outfile == '\0') {
@ -1141,11 +1134,10 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
if (symbol->symbology < 1) {
strcpy(symbol->errtxt, "206: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
/* symbol->symbologys 1 to 86 are defined by tbarcode */
} else if (symbol->symbology == 5) {
symbol->symbology = BARCODE_C25STANDARD;
@ -1158,16 +1150,15 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
} else if (symbol->symbology == 19) {
strcpy(symbol->errtxt, "207: Codabar 18 not supported");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODABAR;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODABAR;
warn_number = ZINT_WARN_INVALID_OPTION;
} else if (symbol->symbology == 26) {
symbol->symbology = BARCODE_UPCA;
} else if (symbol->symbology == 27) {
strcpy(symbol->errtxt, "208: UPCD1 not supported");
error_number = ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
} else if (symbol->symbology == 33) {
symbol->symbology = BARCODE_GS1_128;
} else if (symbol->symbology == 36) {
@ -1181,11 +1172,10 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
} else if (symbol->symbology == 54) {
strcpy(symbol->errtxt, "210: General Parcel Code not supported");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
} else if ((symbol->symbology == 59) || (symbol->symbology == 61)) {
symbol->symbology = BARCODE_CODE128;
} else if (symbol->symbology == 62) {
@ -1201,19 +1191,17 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
} else if (symbol->symbology == 91) {
strcpy(symbol->errtxt, "212: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
} else if ((symbol->symbology >= 94) && (symbol->symbology <= 95)) {
strcpy(symbol->errtxt, "213: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
} else if (symbol->symbology == 100) {
symbol->symbology = BARCODE_HIBC_128;
} else if (symbol->symbology == 101) {
@ -1231,69 +1219,57 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
} else if ((symbol->symbology == 113) || (symbol->symbology == 114)) {
strcpy(symbol->errtxt, "214: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
} else if (symbol->symbology == 115) {
symbol->symbology = BARCODE_DOTCODE;
} else if ((symbol->symbology >= 117) && (symbol->symbology <= 127)) {
if (symbol->symbology != 121) {
strcpy(symbol->errtxt, "215: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
warn_number = ZINT_WARN_INVALID_OPTION;
}
/* Everything from 128 up is Zint-specific */
} else if (symbol->symbology > 145) {
strcpy(symbol->errtxt, "216: Symbology out of range");
if (symbol->warn_level == WARN_FAIL_ALL) {
error_number = ZINT_ERROR_INVALID_OPTION;
} else {
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
}
}
if (error_number >= ZINT_ERROR) {
error_tag(symbol->errtxt, error_number);
return error_number;
warn_number = ZINT_WARN_INVALID_OPTION;
}
}
if (symbol->eci != 0) {
if (!(supports_eci(symbol->symbology))) {
strcpy(symbol->errtxt, "217: Symbology does not support ECI switching");
error_number = ZINT_ERROR_INVALID_OPTION;
} else if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) {
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) {
strcpy(symbol->errtxt, "218: Invalid ECI mode");
error_number = ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
}
if ((symbol->dot_size < 0.01f) || (symbol->dot_size > 20.0f)) {
strcpy(symbol->errtxt, "221: Invalid dot size");
error_number = ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
if ((symbol->input_mode & 0x07) == UNICODE_MODE && !is_valid_utf8(source, in_length)) {
strcpy(symbol->errtxt, "245: Invalid UTF-8");
error_number = ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
if ((symbol->input_mode & 0x07) > 2) {
symbol->input_mode = DATA_MODE; /* Reset completely */
}
if (error_number >= ZINT_ERROR) {
error_tag(symbol->errtxt, error_number);
return error_number;
}
error_buffer = error_number;
#ifndef _MSC_VER
unsigned char local_source[in_length + 1];
#else
@ -1307,8 +1283,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
if (symbol->input_mode & ESCAPE_MODE) {
error_number = escape_char_process(symbol, local_source, &in_length);
if (error_number != 0) {
error_tag(symbol->errtxt, error_number);
return error_number;
return error_tag(symbol->errtxt, error_number);
}
}
@ -1328,19 +1303,18 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
#endif
error_number = gs1_verify(symbol, local_source, in_length, reduced);
if (error_number != 0) {
if (is_composite(symbol->symbology)) {
strcat(symbol->errtxt, " in 2D component");
const char in_2d_comp[] = " in 2D component";
if (is_composite(symbol->symbology) && strlen(symbol->errtxt) < 100 - strlen(in_2d_comp)) {
strcat(symbol->errtxt, in_2d_comp);
}
error_tag(symbol->errtxt, error_number);
return error_number;
return error_tag(symbol->errtxt, error_number);
}
ustrcpy(local_source, reduced); // Cannot contain nul char
in_length = (int) ustrlen(local_source);
}
} else {
strcpy(symbol->errtxt, "220: Selected symbology does not support GS1 mode");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
}
@ -1358,14 +1332,14 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
if (!(symbol->debug & ZINT_DEBUG_TEST)) {
strcpy(symbol->errtxt, "222: Encoded data includes ECI");
}
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Data ECI %d\n", symbol->eci);
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", symbol->eci);
}
}
if (error_number == 0) {
error_number = error_buffer;
error_number = warn_number;
}
error_tag(symbol->errtxt, error_number);
(void)error_tag(symbol->errtxt, error_number);
if (error_number < ZINT_ERROR) {
check_row_heights(symbol);
@ -1387,15 +1361,14 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
break;
default:
strcpy(symbol->errtxt, "223: Invalid rotation angle");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
break;
}
if (symbol->output_options & BARCODE_DOTTY_MODE) {
if (!(is_dotty(symbol->symbology))) {
strcpy(symbol->errtxt, "224: Selected symbology cannot be rendered as dots");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
}
@ -1412,55 +1385,53 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
symbol->text[0] = '\0';
}
error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE);
} else
if (!(strcmp(output, "BMP"))) {
} else if (!(strcmp(output, "BMP"))) {
if (symbol->scale < 1.0f) {
symbol->text[0] = '\0';
}
error_number = plot_raster(symbol, rotate_angle, OUT_BMP_FILE);
} else
if (!(strcmp(output, "PCX"))) {
} else if (!(strcmp(output, "PCX"))) {
if (symbol->scale < 1.0f) {
symbol->text[0] = '\0';
}
error_number = plot_raster(symbol, rotate_angle, OUT_PCX_FILE);
} else
if (!(strcmp(output, "GIF"))) {
} else if (!(strcmp(output, "GIF"))) {
if (symbol->scale < 1.0f) {
symbol->text[0] = '\0';
}
error_number = plot_raster(symbol, rotate_angle, OUT_GIF_FILE);
} else
if (!(strcmp(output, "TIF"))) {
} else if (!(strcmp(output, "TIF"))) {
if (symbol->scale < 1.0f) {
symbol->text[0] = '\0';
}
error_number = plot_raster(symbol, rotate_angle, OUT_TIF_FILE);
} else
if (!(strcmp(output, "TXT"))) {
} else if (!(strcmp(output, "TXT"))) {
error_number = dump_plot(symbol);
} else
if (!(strcmp(output, "EPS"))) {
} else if (!(strcmp(output, "EPS"))) {
error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE);
} else
if (!(strcmp(output, "SVG"))) {
} else if (!(strcmp(output, "SVG"))) {
error_number = plot_vector(symbol, rotate_angle, OUT_SVG_FILE);
} else
if (!(strcmp(output, "EMF"))) {
} else if (!(strcmp(output, "EMF"))) {
error_number = plot_vector(symbol, rotate_angle, OUT_EMF_FILE);
} else {
strcpy(symbol->errtxt, "225: Unknown output format");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
} else {
strcpy(symbol->errtxt, "226: Unknown output format");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
error_tag(symbol->errtxt, error_number);
return error_number;
return error_tag(symbol->errtxt, error_number);
}
int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
@ -1476,21 +1447,19 @@ int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
break;
default:
strcpy(symbol->errtxt, "228: Invalid rotation angle");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
break;
}
if (symbol->output_options & BARCODE_DOTTY_MODE) {
if (!(is_dotty(symbol->symbology))) {
strcpy(symbol->errtxt, "237: Selected symbology cannot be rendered as dots");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
}
error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER);
error_tag(symbol->errtxt, error_number);
return error_number;
return error_tag(symbol->errtxt, error_number);
}
int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) {
@ -1506,21 +1475,19 @@ int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) {
break;
default:
strcpy(symbol->errtxt, "219: Invalid rotation angle");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
break;
}
if (symbol->output_options & BARCODE_DOTTY_MODE) {
if (!(is_dotty(symbol->symbology))) {
strcpy(symbol->errtxt, "238: Selected symbology cannot be rendered as dots");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
return ZINT_ERROR_INVALID_OPTION;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
}
}
error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER);
error_tag(symbol->errtxt, error_number);
return error_number;
return error_tag(symbol->errtxt, error_number);
}
int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) {
@ -1589,8 +1556,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
if (!filename) {
strcpy(symbol->errtxt, "239: Filename NULL");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
if (!strcmp(filename, "-")) {
@ -1600,8 +1566,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
file = fopen(filename, "rb");
if (!file) {
sprintf(symbol->errtxt, "229: Unable to read input file (%.30s)", strerror(errno));
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
file_opened = 1;
@ -1613,15 +1578,13 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
/* On many Linux distros ftell() returns LONG_MAX not -1 on error */
if (fileLen <= 0 || fileLen == LONG_MAX) {
strcpy(symbol->errtxt, "235: Input file empty or unseekable");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
fclose(file);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
if (fileLen > ZINT_MAX_DATA_LEN) {
strcpy(symbol->errtxt, "230: Input file too long");
error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG);
fclose(file);
return ZINT_ERROR_TOO_LONG;
return error_tag(symbol->errtxt, ZINT_ERROR_TOO_LONG);
}
}
@ -1629,11 +1592,10 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
buffer = (unsigned char *) malloc(fileLen);
if (!buffer) {
strcpy(symbol->errtxt, "231: Internal memory error");
error_tag(symbol->errtxt, ZINT_ERROR_MEMORY);
if (file_opened) {
fclose(file);
}
return ZINT_ERROR_MEMORY;
return error_tag(symbol->errtxt, ZINT_ERROR_MEMORY);
}
/* Read file contents into buffer */
@ -1642,12 +1604,11 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
n = fread(buffer + nRead, 1, fileLen - nRead, file);
if (ferror(file)) {
sprintf(symbol->errtxt, "241: Input file read error (%.30s)", strerror(errno));
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
if (file_opened) {
fclose(file);
}
free(buffer);
return ZINT_ERROR_INVALID_DATA;
return error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
}
nRead += n;
} while (!feof(file) && (0 < n) && (nRead < fileLen));

View File

@ -50,26 +50,53 @@ static void test_checks(int index, int debug) {
int ret;
char *expected;
int expected_symbology;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { BARCODE_CODE128, "1234", -1, -1, 3, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching" },
/* 1*/ { BARCODE_CODE128, "1234", -1, -1, 0, -1, -1, 0, "" },
/* 2*/ { BARCODE_QRCODE, "1234", -1, -1, 3, -1, -1, 0, "" },
/* 3*/ { BARCODE_QRCODE, "1234", -1, -1, 999999 + 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI mode" },
/* 4*/ { BARCODE_CODE128, "1234", -1, -1, -1, 20.1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" },
/* 5*/ { BARCODE_CODE128, "1234", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 220: Selected symbology does not support GS1 mode" },
/* 6*/ { BARCODE_GS1_128, "[21]12\0004", 8, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 262: NUL characters not permitted in GS1 mode" },
/* 7*/ { BARCODE_GS1_128, "[21]12é4", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 250: Extended ASCII characters are not supported by GS1" },
/* 8*/ { BARCODE_GS1_128, "[21]12\0074", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 251: Control characters are not supported by GS1" },
/* 9*/ { BARCODE_GS1_128, "[21]1234", -1, GS1_MODE, -1, -1, -1, 0, "" },
/* 10*/ { 0, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 206: Symbology out of range" },
/* 11*/ { 0, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" },
/* 12*/ { 0, "1", -1, -1, 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching" }, // Not supporting beats invalid ECI
/* 13*/ { 0, "1", -1, -1, 1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" },
/* 14*/ { 0, "1", -1, -1, -1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" },
/* 15*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range" },
/* 16*/ { 0, "1", -1, -1, 1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size" }, // Invalid dot size beats invalid ECI
/* 0*/ { BARCODE_CODE128, "1234", -1, -1, 3, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", -1 },
/* 1*/ { BARCODE_CODE128, "1234", -1, -1, 0, -1, -1, 0, "", -1 },
/* 2*/ { BARCODE_QRCODE, "1234", -1, -1, 3, -1, -1, 0, "", -1 },
/* 3*/ { BARCODE_QRCODE, "1234", -1, -1, 999999 + 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI mode", -1 },
/* 4*/ { BARCODE_CODE128, "1234", -1, -1, -1, 20.1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size", -1 },
/* 5*/ { BARCODE_CODE128, "1234", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 220: Selected symbology does not support GS1 mode", -1 },
/* 6*/ { BARCODE_GS1_128, "[21]12\0004", 8, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 262: NUL characters not permitted in GS1 mode", -1 },
/* 7*/ { BARCODE_GS1_128, "[21]12é4", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 250: Extended ASCII characters are not supported by GS1", -1 },
/* 8*/ { BARCODE_GS1_128, "[21]12\0074", -1, GS1_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 251: Control characters are not supported by GS1", -1 },
/* 9*/ { BARCODE_GS1_128, "[21]1234", -1, GS1_MODE, -1, -1, -1, 0, "", -1 },
/* 10*/ { 0, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 206: Symbology out of range", BARCODE_CODE128 },
/* 11*/ { 0, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 },
/* 12*/ { 0, "1", -1, -1, 1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", BARCODE_CODE128 }, // Not supporting beats invalid ECI
/* 13*/ { 0, "1", -1, -1, 1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 },
/* 14*/ { 0, "1", -1, -1, -1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Invalid dot size", BARCODE_CODE128 },
/* 15*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 },
/* 16*/ { 0, "1", -1, -1, 1, 0.009, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", BARCODE_CODE128 }, // Invalid dot size no longer beats invalid ECI
/* 17*/ { 0, "1", -1, -1, -1, 0.009, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 206: Symbology out of range", -1 },
/* 18*/ { 5, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_C25STANDARD },
/* 19*/ { 5, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_C25STANDARD },
/* 20*/ { 12, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_EANX },
/* 21*/ { 12, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_EANX },
/* 22*/ { 19, "1", -1, -1, -1, -1, -1, ZINT_ERROR_TOO_LONG, "Error 362: Input too short", BARCODE_CODABAR },
/* 23*/ { 19, "A1B", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 207: Codabar 18 not supported", BARCODE_CODABAR },
/* 24*/ { 19, "A1B", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 207: Codabar 18 not supported", -1 },
/* 25*/ { 26, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_UPCA },
/* 26*/ { 26, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_UPCA },
/* 27*/ { 27, "1", -1, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 208: UPCD1 not supported", 27 },
/* 28*/ { 54, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 210: General Parcel Code not supported", BARCODE_CODE128 },
/* 29*/ { 54, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 210: General Parcel Code not supported", -1 },
/* 30*/ { 91, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 212: Symbology out of range", BARCODE_CODE128 },
/* 31*/ { 91, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 212: Symbology out of range", -1 },
/* 32*/ { 95, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 213: Symbology out of range", BARCODE_CODE128 },
/* 33*/ { 95, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 213: Symbology out of range", -1 },
/* 34*/ { 111, "1", -1, -1, -1, -1, -1, 0, "", BARCODE_HIBC_BLOCKF },
/* 35*/ { 111, "1", -1, -1, -1, -1, WARN_FAIL_ALL, 0, "", BARCODE_HIBC_BLOCKF },
/* 36*/ { 114, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 214: Symbology out of range", BARCODE_CODE128 },
/* 37*/ { 114, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 214: Symbology out of range", -1 },
/* 38*/ { 120, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 215: Symbology out of range", BARCODE_CODE128 },
/* 39*/ { 120, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 215: Symbology out of range", -1 },
/* 40*/ { 146, "1", -1, -1, -1, -1, -1, ZINT_WARN_INVALID_OPTION, "Warning 216: Symbology out of range", BARCODE_CODE128 },
/* 41*/ { 146, "1", -1, -1, -1, -1, WARN_FAIL_ALL, ZINT_ERROR_INVALID_OPTION, "Error 216: Symbology out of range", -1 },
/* 42*/ { BARCODE_CODE128, "\200", -1, UNICODE_MODE, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8", -1 },
};
int data_size = sizeof(data) / sizeof(struct item);
@ -80,22 +107,13 @@ static void test_checks(int index, int debug) {
struct zint_symbol *symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = data[i].symbology;
if (data[i].input_mode != -1) {
symbol->input_mode = data[i].input_mode;
}
if (data[i].eci != -1) {
symbol->eci = data[i].eci;
}
int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
if (data[i].dot_size != -1) {
symbol->dot_size = data[i].dot_size;
}
if (data[i].warn_level != -1) {
symbol->warn_level = data[i].warn_level;
}
symbol->debug |= debug;
int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode(%d) ret %d != %d (%s)\n", i, data[i].symbology, ret, data[i].ret, symbol->errtxt);
@ -103,6 +121,12 @@ static void test_checks(int index, int debug) {
ret = strcmp(symbol->errtxt, data[i].expected);
assert_zero(ret, "i:%d (%d) strcmp(%s, %s) %d != 0\n", i, data[i].symbology, symbol->errtxt, data[i].expected, ret);
if (data[i].expected_symbology == -1) {
assert_equal(symbol->symbology, data[i].symbology, "i:%d symbol->symbology %d != original %d\n", i, symbol->symbology, data[i].symbology);
} else {
assert_equal(symbol->symbology, data[i].expected_symbology, "i:%d symbol->symbology %d != expected %d\n", i, symbol->symbology, data[i].expected_symbology);
}
ZBarcode_Delete(symbol);
}
@ -450,6 +474,117 @@ static void test_valid_id(void) {
testFinish();
}
static void test_error_tag(int index) {
testStart("");
int ret;
struct item {
int error_number;
char* data;
int ret;
char* expected;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { ZINT_WARN_INVALID_OPTION, "", ZINT_WARN_INVALID_OPTION, "Warning " },
/* 1*/ { ZINT_ERROR_TOO_LONG, "", ZINT_ERROR_TOO_LONG, "Error " },
/* 2*/ { ZINT_WARN_USES_ECI, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", ZINT_WARN_USES_ECI, "Warning 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" },
/* 3*/ { ZINT_ERROR_INVALID_DATA, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", ZINT_ERROR_INVALID_DATA, "Error 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123" },
};
int data_size = ARRAY_SIZE(data);
char errtxt[100];
for (int i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
assert_nonzero(strlen(data[i].data) < 100, "i:%d strlen(data) %d >= 100\n", i, (int) strlen(data[i].data));
strcpy(errtxt, data[i].data);
ret = error_tag(errtxt, data[i].error_number);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
assert_zero(strcmp(errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, errtxt, data[i].expected);
assert_nonzero(strlen(errtxt) >= strlen(data[i].data), "i:%d strlen(errtxt) %d < %d\n", i, (int) strlen(errtxt), (int) strlen(data[i].data));
}
testFinish();
}
STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length);
static void test_strip_bom(void) {
testStart("");
int ret;
char data[] = "\357\273\277A"; // U+FEFF BOM, with "A"
int length;
char buf[6];
strcpy(buf, data);
length = (int) strlen(buf);
strip_bom((unsigned char *) buf, &length);
assert_equal(length, 1, "length %d != 1\n", length);
assert_zero(buf[1], "buf[1] %d != 0\n", buf[1]);
// BOM not stripped if only data
char bom_only[] = "\357\273\277"; // U+FEFF BOM only
strcpy(buf, bom_only);
length = (int) strlen(buf);
strip_bom((unsigned char *) buf, &length);
assert_equal(length, 3, "BOM only length %d != 3\n", length);
ret = strcmp(buf, bom_only);
assert_zero(ret, "BOM only strcmp ret %d != 0\n", ret);
testFinish();
}
STATIC_UNLESS_ZINT_TEST int is_valid_utf8(const unsigned char source[], const int length);
static void test_is_valid_utf8(int index) {
testStart("");
int ret;
struct item {
char* data;
int length;
int ret;
char* comment;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { "", -1, 1, "" },
/* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" },
/* 2*/ { "éa", -1, 1, "" },
/* 3*/ { "a\000b", 3, 1, "Embedded nul" },
/* 4*/ { "\357\273\277a", -1, 1, "Bom" },
/* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" },
/* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" },
/* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" },
/* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" },
};
int data_size = ARRAY_SIZE(data);
for (int i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = is_valid_utf8((const unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
}
testFinish();
}
STATIC_UNLESS_ZINT_TEST int error_tag(char error_string[100], int error_number);
int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -461,6 +596,9 @@ int main(int argc, char *argv[]) {
{ "test_encode_file_directory", test_encode_file_directory, 0, 0, 0 },
{ "test_bad_args", test_bad_args, 0, 0, 0 },
{ "test_valid_id", test_valid_id, 0, 0, 0 },
{ "test_error_tag", test_error_tag, 1, 0, 0 },
{ "test_strip_bom", test_strip_bom, 0, 0, 0 },
{ "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 },
};
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));