1 /*
2     libzint - the open source barcode library
3     Copyright (C) 2020 - 2021 Robin Stuart <rstuart114@gmail.com>
4 
5     Redistribution and use in source and binary forms, with or without
6     modification, are permitted provided that the following conditions
7     are met:
8 
9     1. Redistributions of source code must retain the above copyright
10        notice, this list of conditions and the following disclaimer.
11     2. Redistributions in binary form must reproduce the above copyright
12        notice, this list of conditions and the following disclaimer in the
13        documentation and/or other materials provided with the distribution.
14     3. Neither the name of the project nor the names of its contributors
15        may be used to endorse or promote products derived from this software
16        without specific prior written permission.
17 
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28     SUCH DAMAGE.
29  */
30 /* vim: set ts=4 sw=4 et : */
31 
32 #include "testcommon.h"
33 
test_large(int index,int debug)34 static void test_large(int index, int debug) {
35 
36     struct item {
37         int symbology;
38         char *pattern;
39         int length;
40         int ret;
41         int expected_rows;
42         int expected_width;
43     };
44     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
45     struct item data[] = {
46         /*  0*/ { BARCODE_AUSPOST, "1", 23, 0, 3, 133 },
47         /*  1*/ { BARCODE_AUSPOST, "1", 24, ZINT_ERROR_TOO_LONG, -1, -1 },
48         /*  2*/ { BARCODE_AUSPOST, "1", 18, 0, 3, 133 },
49         /*  3*/ { BARCODE_AUSPOST, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 },
50         /*  4*/ { BARCODE_AUSPOST, "1", 16, 0, 3, 103 },
51         /*  5*/ { BARCODE_AUSPOST, "1", 17, ZINT_ERROR_TOO_LONG, -1, -1 },
52         /*  6*/ { BARCODE_AUSPOST, "1", 13, 0, 3, 103 },
53         /*  7*/ { BARCODE_AUSPOST, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1 },
54         /*  8*/ { BARCODE_AUSPOST, "1", 8, 0, 3, 73 },
55         /*  9*/ { BARCODE_AUSPOST, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
56         /* 10*/ { BARCODE_AUSREPLY, "1", 8, 0, 3, 73 },
57         /* 11*/ { BARCODE_AUSREPLY, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
58         /* 12*/ { BARCODE_AUSROUTE, "1", 8, 0, 3, 73 },
59         /* 13*/ { BARCODE_AUSROUTE, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
60         /* 14*/ { BARCODE_AUSREDIRECT, "1", 8, 0, 3, 73 },
61         /* 15*/ { BARCODE_AUSREDIRECT, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
62     };
63     int data_size = ARRAY_SIZE(data);
64     int i, length, ret;
65     struct zint_symbol *symbol;
66 
67     char data_buf[64];
68 
69     testStart("test_large");
70 
71     for (i = 0; i < data_size; i++) {
72 
73         if (index != -1 && i != index) continue;
74 
75         symbol = ZBarcode_Create();
76         assert_nonnull(symbol, "Symbol not created\n");
77 
78         testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length);
79         assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf));
80 
81         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug);
82 
83         ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length);
84         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
85 
86         if (ret < ZINT_ERROR) {
87             assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
88             assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
89         }
90 
91         ZBarcode_Delete(symbol);
92     }
93 
94     testFinish();
95 }
96 
test_hrt(int index,int debug)97 static void test_hrt(int index, int debug) {
98 
99     struct item {
100         int symbology;
101         char *data;
102 
103         char *expected;
104     };
105     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
106     struct item data[] = {
107         /*  0*/ { BARCODE_AUSPOST, "12345678901234567890123", "" }, // None
108     };
109     int data_size = ARRAY_SIZE(data);
110     int i, length, ret;
111     struct zint_symbol *symbol;
112 
113     testStart("test_hrt");
114 
115     for (i = 0; i < data_size; i++) {
116 
117         if (index != -1 && i != index) continue;
118 
119         symbol = ZBarcode_Create();
120         assert_nonnull(symbol, "Symbol not created\n");
121 
122         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
123 
124         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
125         assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt);
126 
127         assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected);
128 
129         ZBarcode_Delete(symbol);
130     }
131 
132     testFinish();
133 }
134 
test_input(int index,int debug)135 static void test_input(int index, int debug) {
136 
137     struct item {
138         int symbology;
139         char *data;
140         int ret;
141         int expected_rows;
142         int expected_width;
143         char *expected_errtxt;
144     };
145     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
146     struct item data[] = {
147         /*  0*/ { BARCODE_AUSPOST, "12345678", 0, 3, 73, "" },
148         /*  1*/ { BARCODE_AUSPOST, "1234567A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 405: Invalid character in DPID (first 8 characters) (digits only)" },
149         /*  2*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
150         /*  3*/ { BARCODE_AUSPOST, "12345678ABcd!", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 404: Invalid character in data (alphanumerics, space and \"#\" only)" },
151         /*  4*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
152         /*  5*/ { BARCODE_AUSPOST, "1234567890123456", 0, 3, 103, "" },
153         /*  6*/ { BARCODE_AUSPOST, "123456789012345A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character in data (digits only for lengths 16 and 23)" },
154         /*  7*/ { BARCODE_AUSPOST, "12345678ABCDefgh #", 0, 3, 133, "" }, // Length 18
155         /*  8*/ { BARCODE_AUSPOST, "12345678901234567890123", 0, 3, 133, "" },
156         /*  9*/ { BARCODE_AUSPOST, "1234567890123456789012A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character in data (digits only for lengths 16 and 23)" },
157         /* 10*/ { BARCODE_AUSPOST, "1234567", ZINT_ERROR_TOO_LONG, -1, -1, "Error 401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)" }, // No leading zeroes added
158         /* 11*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "" },
159         /* 12*/ { BARCODE_AUSREPLY, "1234567", 0, 3, 73, "" }, // Leading zeroes added
160         /* 13*/ { BARCODE_AUSREPLY, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
161         /* 14*/ { BARCODE_AUSROUTE, "123456", 0, 3, 73, "" },
162         /* 15*/ { BARCODE_AUSROUTE, "12345", 0, 3, 73, "" },
163         /* 16*/ { BARCODE_AUSROUTE, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
164         /* 17*/ { BARCODE_AUSREDIRECT, "1234", 0, 3, 73, "" },
165         /* 18*/ { BARCODE_AUSREDIRECT, "123", 0, 3, 73, "" },
166         /* 19*/ { BARCODE_AUSREDIRECT, "0", 0, 3, 73, "" },
167         /* 20*/ { BARCODE_AUSREDIRECT, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
168     };
169     int data_size = ARRAY_SIZE(data);
170     int i, length, ret;
171     struct zint_symbol *symbol;
172 
173     testStart("test_input");
174 
175     for (i = 0; i < data_size; i++) {
176 
177         if (index != -1 && i != index) continue;
178 
179         symbol = ZBarcode_Create();
180         assert_nonnull(symbol, "Symbol not created\n");
181 
182         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
183 
184         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
185         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
186 
187         if (ret < ZINT_ERROR) {
188             assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
189             assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
190         }
191         assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt);
192 
193         ZBarcode_Delete(symbol);
194     }
195 
196     testFinish();
197 }
198 
199 // Australia Post Customer Barcoding Technical Specifications (Revised Aug 2012)
200 // https://auspost.com.au/content/dam/auspost_corp/media/documents/customer-barcode-technical-specifications-aug2012.pdf
test_encode(int index,int generate,int debug)201 static void test_encode(int index, int generate, int debug) {
202 
203     struct item {
204         int symbology;
205         char *data;
206         int ret;
207 
208         int expected_rows;
209         int expected_width;
210         char *comment;
211         char *expected;
212     };
213     struct item data[] = {
214         /*  0*/ { BARCODE_AUSPOST, "96184209", 0, 3, 73, "Australia Post Customer Barcoding Tech Specs Diagram 1; verified manually against tec-it",
215                     "1000101010100010001010100000101010001010001000001010000010001000001000100"
216                     "1010101010101010101010101010101010101010101010101010101010101010101010101"
217                     "0000100010000010101010001010000010101010001000101010001000100010000010000"
218                 },
219         /*  1*/ { BARCODE_AUSPOST, "3221132412345678", 0, 3, 103, "59 Custom 2 N encoding",
220                     "1000100000101010100010001010101010101000101010101000101010101000001000100000101000000000001000000000100"
221                     "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
222                     "0000001000100010101010101000100000101010000010001010001000000010101010001010000010001010101000100000000"
223                 },
224         /*  2*/ { BARCODE_AUSPOST, "32211324Ab #2", 0, 3, 103, "59 Custom 2 C encoding",
225                     "1000100000101010100010001010101010101000101010101010001010100010100000101000100000000010100000100010100"
226                     "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
227                     "0000001000100010101010101000100000101010000010101010001010100010000000100000001000101010000010000000000"
228                 },
229         /*  3*/ { BARCODE_AUSPOST, "32211324123456789012345", 0, 3, 133, "62 Custom 3 N encoding",
230                     "1000001010001010100010001010101010101000101010101000101010101000001000100000001010101010100010101010100000100000100010101010100010100"
231                     "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
232                     "0000101010100010101010101000100000101010000010001010001000000010101010001010001010101000101000100000001000001010000010001010100010000"
233                 },
234         /*  4*/ { BARCODE_AUSPOST, "32211324aBCd#F hIz", 0, 3, 133, "62 Custom 3 C encoding",
235                     "1000001010001010100010001010101010101000101010000010101010100010000010100010100010100010000010000000000000100010100010101010000000100"
236                     "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
237                     "0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000"
238                 },
239         /*  5*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it",
240                     "1000101010001010100010101010100000100010000000001000001000000000100010100"
241                     "1010101010101010101010101010101010101010101010101010101010101010101010101"
242                     "0000000000101000101000100000001010101000101000000000100010101000101000000"
243                 },
244         /*  6*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it",
245                     "1000000000101010101010000010001000000010101000100010101010000000101000100"
246                     "1010101010101010101010101010101010101010101010101010101010101010101010101"
247                     "0000101010000010000000101010100010100010101000100010101010001010001000000"
248                 },
249         /*  7*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it",
250                     "1000001010000010000000100010100010101010100000101010101000100010100010100"
251                     "1010101010101010101010101010101010101010101010101010101010101010101010101"
252                     "0000001010100010101010001010001000000010101000000000001010101000001010000"
253                 },
254     };
255     int data_size = ARRAY_SIZE(data);
256     int i, length, ret;
257     struct zint_symbol *symbol;
258 
259     char escaped[1024];
260     char bwipp_buf[8192];
261     char bwipp_msg[1024];
262 
263     int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise
264 
265     testStart("test_encode");
266 
267     for (i = 0; i < data_size; i++) {
268 
269         if (index != -1 && i != index) continue;
270 
271         symbol = ZBarcode_Create();
272         assert_nonnull(symbol, "Symbol not created\n");
273 
274         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
275 
276         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
277         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
278 
279         if (generate) {
280             printf("        /*%3d*/ { %s, \"%s\", %s, %d, %d, \"%s\",\n",
281                     i, testUtilBarcodeName(data[i].symbology), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
282                     testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment);
283             testUtilModulesPrint(symbol, "                    ", "\n");
284             printf("                },\n");
285         } else {
286             if (ret < ZINT_ERROR) {
287                 int width, row;
288 
289                 assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data);
290                 assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
291 
292                 ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
293                 assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
294 
295                 if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) {
296                     ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf));
297                     assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
298 
299                     ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
300                     assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n  actual: %s\nexpected: %s\n",
301                                    i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected);
302                 }
303             }
304         }
305 
306         ZBarcode_Delete(symbol);
307     }
308 
309     testFinish();
310 }
311 
312 // #181 Christian Hartlage OSS-Fuzz
test_fuzz(int index,int debug)313 static void test_fuzz(int index, int debug) {
314 
315     struct item {
316         int symbology;
317         char *data;
318         int length;
319         int ret;
320     };
321     // s/\/\*[ 0-9]*\*\//\=printf("\/*%2d*\/", line(".") - line("'<"))
322     struct item data[] = {
323         /* 0*/ { BARCODE_AUSROUTE, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
324         /* 1*/ { BARCODE_AUSROUTE, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
325         /* 2*/ { BARCODE_AUSREPLY, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
326         /* 3*/ { BARCODE_AUSREPLY, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
327         /* 4*/ { BARCODE_AUSREDIRECT, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
328         /* 5*/ { BARCODE_AUSREDIRECT, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
329     };
330     int data_size = ARRAY_SIZE(data);
331     int i, length, ret;
332     struct zint_symbol *symbol;
333 
334     testStart("test_fuzz");
335 
336     for (i = 0; i < data_size; i++) {
337 
338         if (index != -1 && i != index) continue;
339 
340         symbol = ZBarcode_Create();
341         assert_nonnull(symbol, "Symbol not created\n");
342 
343         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
344 
345         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
346         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
347 
348         ZBarcode_Delete(symbol);
349     }
350 
351     testFinish();
352 }
353 
main(int argc,char * argv[])354 int main(int argc, char *argv[]) {
355 
356     testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
357         { "test_large", test_large, 1, 0, 1 },
358         { "test_hrt", test_hrt, 1, 0, 1 },
359         { "test_input", test_input, 1, 0, 1 },
360         { "test_encode", test_encode, 1, 1, 1 },
361         { "test_fuzz", test_fuzz, 1, 0, 1 },
362     };
363 
364     testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
365 
366     testReport();
367 
368     return 0;
369 }
370