diff --git a/backend/library.c b/backend/library.c index 86e54c2d..884aad2d 100644 --- a/backend/library.c +++ b/backend/library.c @@ -1536,6 +1536,7 @@ int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, unsigned char int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { FILE *file; + int file_opened = 0; unsigned char *buffer; long fileLen; size_t n; @@ -1552,7 +1553,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { if (!strcmp(filename, "-")) { file = stdin; - fileLen = 7900; + fileLen = ZINT_MAX_FILE_LEN; } else { file = fopen(filename, "rb"); if (!file) { @@ -1560,21 +1561,21 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); return ZINT_ERROR_INVALID_DATA; } + file_opened = 1; /* Get file length */ fseek(file, 0, SEEK_END); fileLen = ftell(file); fseek(file, 0, SEEK_SET); - if (fileLen > 7900 && fileLen != LONG_MAX) { /* On many Linux distros ftell() returns LONG_MAX not -1 on error */ - /* The largest amount of data that can be encoded is 7827 numeric digits in Han Xin Code */ - strcpy(symbol->errtxt, "230: Input file too long"); + if (fileLen <= 0 || fileLen == LONG_MAX) { /* On many Linux distros ftell() returns LONG_MAX not -1 on error */ + strcpy(symbol->errtxt, "235: Input file empty or unseekable"); error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); fclose(file); return ZINT_ERROR_INVALID_DATA; } - if (fileLen <= 0 || fileLen == LONG_MAX) { - strcpy(symbol->errtxt, "235: Input file empty or unseekable"); + if (fileLen > ZINT_MAX_FILE_LEN) { + strcpy(symbol->errtxt, "230: Input file too long"); error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); fclose(file); return ZINT_ERROR_INVALID_DATA; @@ -1586,7 +1587,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { if (!buffer) { strcpy(symbol->errtxt, "231: Internal memory error"); error_tag(symbol->errtxt, ZINT_ERROR_MEMORY); - if (strcmp(filename, "-")) { + if (file_opened) { fclose(file); } return ZINT_ERROR_MEMORY; @@ -1599,7 +1600,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { if (ferror(file)) { sprintf(symbol->errtxt, "241: Input file read error (%.30s)", strerror(errno)); error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); - if (strcmp(filename, "-")) { + if (file_opened) { fclose(file); } free(buffer); @@ -1608,7 +1609,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { nRead += n; } while (!feof(file) && (0 < n) && (nRead < fileLen)); - if (strcmp(filename, "-")) { + if (file_opened) { fclose(file); } ret = ZBarcode_Encode(symbol, buffer, nRead); diff --git a/backend/zint.h b/backend/zint.h index f4eb99f4..acf676cb 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -306,6 +306,9 @@ extern "C" { #define ZINT_CAP_FULL_MULTIBYTE 0x0400 #define ZINT_CAP_MASK 0x0800 +// The largest amount of data that can be encoded is 4350 4-byte UTF-8 chars in Han Xin Code +#define ZINT_MAX_FILE_LEN 17400 + // Debug flags #define ZINT_DEBUG_PRINT 1 #define ZINT_DEBUG_TEST 2 diff --git a/frontend/main.c b/frontend/main.c index 5da27f6b..799dd406 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -296,7 +296,7 @@ static int is_raster(char *filetype) { static int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, char *filetype, int rotate_angle) { FILE *file; - unsigned char buffer[7828] = {0}; // 7828 maximum HanXin input + unsigned char buffer[ZINT_MAX_FILE_LEN] = {0}; // Maximum HanXin input unsigned char character = 0; int posn = 0, error_number = 0, line_count = 1; char output_file[256]; diff --git a/frontend/tests/test_args.c b/frontend/tests/test_args.c index 1d342841..e4d29fc2 100644 --- a/frontend/tests/test_args.c +++ b/frontend/tests/test_args.c @@ -56,7 +56,7 @@ static char *exec(const char *cmd, char *buf, int buf_size, int debug, int index if (cnt) { if (buf[cnt - 1] == '\r' || buf[cnt - 1] == '\n') { buf[cnt - 1] = '\0'; - if (buf[cnt - 2] == '\r' || buf[cnt - 2] == '\n') { + if (cnt > 1 && (buf[cnt - 2] == '\r' || buf[cnt - 2] == '\n')) { buf[cnt - 2] = '\0'; } } @@ -93,18 +93,20 @@ static int arg_input(char *cmd, const char *filename, const char *input) { FILE *fp; int cnt; if (input != NULL) { - fp = fopen(filename, "wb"); - if (!fp) { - fprintf(stderr, "arg_input: failed to open '%s' for writing\n", filename); - return 0; - } - cnt = fwrite(input, 1, strlen(input), fp); - if (cnt != (int) strlen(input)) { - fprintf(stderr, "arg_input: failed to write %d bytes, cnt %d written (%s)\n", (int) strlen(input), cnt, filename); + if (strcmp(input, "-") != 0) { + fp = fopen(filename, "wb"); + if (!fp) { + fprintf(stderr, "arg_input: failed to open '%s' for writing\n", filename); + return 0; + } + cnt = fwrite(input, 1, strlen(input), fp); + if (cnt != (int) strlen(input)) { + fprintf(stderr, "arg_input: failed to write %d bytes, cnt %d written (%s)\n", (int) strlen(input), cnt, filename); + fclose(fp); + return 0; + } fclose(fp); - return 0; } - fclose(fp); sprintf(cmd + (int) strlen(cmd), "%s-i '%s'", strlen(cmd) ? " " : "", filename); return 1; } @@ -279,7 +281,7 @@ static void test_dump_args(int index, int debug) { } testFinish(); -} +} static void test_input(int index, int debug) { @@ -348,7 +350,50 @@ static void test_input(int index, int debug) { } testFinish(); -} +} + +static void test_stdin_input(int index, int debug) { + + testStart(""); + + struct item { + int b; + char *data; + char *input; + char *outfile; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, "123", "-", "test_stdin_input.png" }, + }; + int data_size = ARRAY_SIZE(data); + + char cmd[4096]; + char buf[4096]; + + char *input_filename = "-"; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + sprintf(cmd, "echo '%s' | zint", data[i].data); + if (debug & ZINT_DEBUG_PRINT) { + strcat(cmd, " --verbose"); + } + + arg_int(cmd, "-b ", data[i].b); + arg_input(cmd, input_filename, data[i].input); + arg_data(cmd, "-o ", data[i].outfile); + + assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i), "i:%d exec(%s) NULL\n", i, cmd); + + assert_nonzero(testUtilExists(data[i].outfile), "i:%d testUtilExists(%s) != 1\n", i, data[i].outfile); + //assert_zero(remove(data[i].outfile), "i:%d remove(%s) != 0 (%d)\n", i, data[i].outfile, errno); + } + + testFinish(); +} // Note ordering of `--batch` before/after data/input args affects error messages static void test_batch_input(int index, int debug) { @@ -407,7 +452,7 @@ static void test_batch_input(int index, int debug) { } testFinish(); -} +} static void test_batch_large(int index, int debug) { @@ -465,7 +510,7 @@ static void test_batch_large(int index, int debug) { } testFinish(); -} +} static void test_checks(int index, int debug) { @@ -566,13 +611,14 @@ static void test_checks(int index, int debug) { } testFinish(); -} +} int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_dump_args", test_dump_args, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, + { "test_stdin_input", test_stdin_input, 1, 0, 1 }, { "test_batch_input", test_batch_input, 1, 0, 1 }, { "test_batch_large", test_batch_large, 1, 0, 1 }, { "test_checks", test_checks, 1, 0, 1 },