UPCA_CC/EANX_CC: fix out-of-bounds crash in AI resolve loop in

`gs1_verify()` by checking length before `to_int()`, ticket
  #300 (#11), props Andre Maute
CODEONE: fix out-of-bounds crash for Version T by upping buffer
  size to same as for A to H, ticket #300 (#12), props Andre Maute
GS1_128_CC: fix divide-by-zero crash in `calc_padding_ccc()` by
  allowing for min linear width 68 in `cc_width` calc, ticket #300
  (#13), props Andre Maute
BWIPP: update `bwipp_dump.ps` to latest version, update
  `gen_gs1_lint.php` to accommodate `req` "+"
PDF417: change `liste[]` int -> short to lessen stack usage
Some variable name and code fiddlings
This commit is contained in:
gitlost 2023-11-28 08:58:56 +00:00
parent e9203439b7
commit db92c7de57
11 changed files with 132 additions and 89 deletions

View File

@ -112,21 +112,23 @@ Bugs
- GUI: fix not enabling font combo "Small Bold (vector only)" by default - GUI: fix not enabling font combo "Small Bold (vector only)" by default
- CODEONE: fix S/T quiet zone 1X bottom (props BWIPP issue #245 doc) - CODEONE: fix S/T quiet zone 1X bottom (props BWIPP issue #245 doc)
- EAN-2/EAN-5: fix `BARCODE_BIND_TOP/BIND/BOX` output - EAN-2/EAN-5: fix `BARCODE_BIND_TOP/BIND/BOX` output
- PDF417: fix out-of-bounds crash in `pdf_text_submode_length()`, ticket #300, - library: fix 21-bit Unicode conversion in `escape_char_process()`; fix
props Andre Maute restricting escaped data length by using de-escaped length to check
- AZTEC: fix out-of-bounds crash when user-specified size given, ticket #300, - AZTEC: fix out-of-bounds crash when user-specified size given, ticket #300,
props Andre Maute; fix 4-layer compact block max (76 -> 64); fix encoding of props Andre Maute; fix 4-layer compact block max (76 -> 64); fix encoding of
byte-blocks > 11-bit limit byte-blocks > 11-bit limit
- library: fix 21-bit Unicode conversion in `escape_char_process()`; fix
restricting escaped data length by using de-escaped length to check
- CODEONE: fix out-of-bounds crash in `c1_c40text_cnt()` and looping on latch
crash in `c1_encode()`, ticket #300, props Andre Maute
- CODABLOCKF: fix crash due to `columns` overflow, ticket #300, props Andre - CODABLOCKF: fix crash due to `columns` overflow, ticket #300, props Andre
Maute Maute
- EANX_CC/UPCA_CC: fix crash in `dbar_date()` on not checking length, ticket - CODEONE: fix out-of-bounds crash in `c1_c40text_cnt()` and looping on latch
#300, props Andre Maute crash in `c1_encode()` and too small buffer for Version T, ticket #300, props
- PDF417: fix out-of-bounds crash on overrunning string and codeword buffers, Andre Maute
ticket #300, props Andre Maute - EANX_CC/UPCA_CC: fix crash in `dbar_date()` on not checking length and crash
in `gs1_verify()` on not checking length, ticket #300, props Andre Maute
- GS1_128_CC: fix divide-by-zero crash in `calc_padding_ccc()`, ticket #300,
props Andre Maute
- PDF417: fix out-of-bounds crash in `pdf_text_submode_length()` and
out-of-bounds crash on overrunning string and codeword buffers, ticket #300,
props Andre Maute
Version 2.12.0 (2022-12-12) Version 2.12.0 (2022-12-12)

View File

@ -37,6 +37,9 @@
#include "reedsol.h" #include "reedsol.h"
#include "large.h" #include "large.h"
#define C1_MAX_CWS 1480 /* Max data codewords for Version H */
#define C1_MAX_ECCS 560 /* Max ECC codewords for Version H */
#define C1_ASCII 1 #define C1_ASCII 1
#define C1_C40 2 #define C1_C40 2
#define C1_DECIMAL 3 #define C1_DECIMAL 3
@ -851,7 +854,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], int len
} }
} }
if (tp > 1480) { if (tp > C1_MAX_CWS) {
if (debug_print) fputc('\n', stdout); if (debug_print) fputc('\n', stdout);
/* Data is too large for symbol */ /* Data is too large for symbol */
return 0; return 0;
@ -953,7 +956,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], int len
} }
/* Re-check length of data */ /* Re-check length of data */
if (tp > 1480) { if (tp > C1_MAX_CWS) {
/* Data is too large for symbol */ /* Data is too large for symbol */
return 0; return 0;
} }
@ -1135,7 +1138,7 @@ INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const i
} else if (symbol->option_2 == 10) { } else if (symbol->option_2 == 10) {
/* Version T */ /* Version T */
unsigned int target[90 + 2]; /* Allow for 90 BYTE mode (+ latch and byte count) */ unsigned int target[C1_MAX_CWS + C1_MAX_ECCS]; /* Use same buffer size as A to H to avail of loop checks */
unsigned int ecc[22]; unsigned int ecc[22];
int data_length; int data_length;
int data_cw, ecc_cw, block_width; int data_cw, ecc_cw, block_width;
@ -1221,7 +1224,7 @@ INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const i
} else { } else {
/* Versions A to H */ /* Versions A to H */
unsigned int target[1480 + 560]; unsigned int target[C1_MAX_CWS + C1_MAX_ECCS];
unsigned int sub_data[185], sub_ecc[70]; unsigned int sub_data[185], sub_ecc[70];
int data_length; int data_length;
int data_cw; int data_cw;

View File

@ -778,7 +778,7 @@ static int calc_padding_ccb(const int binary_length, const int cc_width) {
return target_bitsize; return target_bitsize;
} }
static int calc_padding_ccc(const int binary_length, int *cc_width, const int linear_width, int *ecc) { static int calc_padding_ccc(const int binary_length, int *p_cc_width, const int linear_width, int *p_ecc_level) {
int target_bitsize = 0; int target_bitsize = 0;
int byte_length, codewords_used, ecc_level, ecc_codewords, rows; int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
int codewords_total, target_codewords, target_bytesize; int codewords_total, target_codewords, target_bytesize;
@ -806,22 +806,25 @@ static int calc_padding_ccc(const int binary_length, int *cc_width, const int li
} else { } else {
return 0; return 0;
} }
*(ecc) = ecc_level; *p_ecc_level = ecc_level;
ecc_codewords = 1 << (ecc_level + 1); ecc_codewords = 1 << (ecc_level + 1);
codewords_used += ecc_codewords; codewords_used += ecc_codewords;
codewords_used += 3; codewords_used += 3;
/* Minimum possible linear width (with GS1_NO_CHECK) is 11*5 (start, FNC1, linkage, data, check) + 13 stop */
assert(linear_width >= 68);
/* -52 = 7 left shift (section 12.3 f) + 10 right quiet zone - 17 start + 2x17 row indicators + 18 stop */ /* -52 = 7 left shift (section 12.3 f) + 10 right quiet zone - 17 start + 2x17 row indicators + 18 stop */
*(cc_width) = (linear_width - 52) / 17; *p_cc_width = linear_width == 68 ? 1 : (linear_width - 52) / 17; /* Ensure > 0 */
if (*(cc_width) > 30) { if (*p_cc_width > 30) {
*(cc_width) = 30; *p_cc_width = 30;
} }
rows = (int) ceil((double) codewords_used / *(cc_width)); assert(*p_cc_width > 0);
rows = (int) ceil((double) codewords_used / *p_cc_width);
/* stop the symbol from becoming too high */ /* stop the symbol from becoming too high */
while (rows > 30 && *(cc_width) < 30) { while (rows > 30 && *p_cc_width < 30) {
*(cc_width) = *(cc_width) + 1; (*p_cc_width)++;
rows = (int) ceil((double) codewords_used / *(cc_width)); rows = (int) ceil((double) codewords_used / *p_cc_width);
} }
if (rows > 30) { /* Should never happen given `codewords_used` check above (865 / 30 ~ 28.83) */ if (rows > 30) { /* Should never happen given `codewords_used` check above (865 / 30 ~ 28.83) */
@ -831,7 +834,7 @@ static int calc_padding_ccc(const int binary_length, int *cc_width, const int li
rows = 3; rows = 3;
} }
codewords_total = *(cc_width) * rows; codewords_total = *p_cc_width * rows;
target_codewords = codewords_total - ecc_codewords; target_codewords = codewords_total - ecc_codewords;
target_codewords -= 3; target_codewords -= 3;
@ -846,7 +849,7 @@ static int calc_padding_ccc(const int binary_length, int *cc_width, const int li
/* Handles all data encodation from section 5 of ISO/IEC 24723 */ /* Handles all data encodation from section 5 of ISO/IEC 24723 */
static int cc_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length, static int cc_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length,
char binary_string[], const int cc_mode, int *cc_width, int *ecc, const int linear_width) { char binary_string[], const int cc_mode, int *p_cc_width, int *p_ecc_level, const int linear_width) {
int encoding_method, read_posn, alpha_pad; int encoding_method, read_posn, alpha_pad;
int i, j, ai_crop, ai_crop_posn, fnc1_latch; int i, j, ai_crop, ai_crop_posn, fnc1_latch;
int ai90_mode, remainder; int ai90_mode, remainder;
@ -863,7 +866,7 @@ static int cc_binary_string(struct zint_symbol *symbol, const unsigned char sour
ai_crop_posn = -1; ai_crop_posn = -1;
fnc1_latch = 0; fnc1_latch = 0;
alpha_pad = 0; alpha_pad = 0;
*ecc = 0; *p_ecc_level = 0;
target_bitsize = 0; target_bitsize = 0;
mode = NUMERIC; mode = NUMERIC;
@ -1133,13 +1136,13 @@ static int cc_binary_string(struct zint_symbol *symbol, const unsigned char sour
switch (cc_mode) { switch (cc_mode) {
case 1: case 1:
target_bitsize = calc_padding_cca(bp, *(cc_width)); target_bitsize = calc_padding_cca(bp, *p_cc_width);
break; break;
case 2: case 2:
target_bitsize = calc_padding_ccb(bp, *(cc_width)); target_bitsize = calc_padding_ccb(bp, *p_cc_width);
break; break;
case 3: case 3:
target_bitsize = calc_padding_ccc(bp, cc_width, linear_width, ecc); target_bitsize = calc_padding_ccc(bp, p_cc_width, linear_width, p_ecc_level);
break; break;
} }
@ -1170,13 +1173,13 @@ static int cc_binary_string(struct zint_symbol *symbol, const unsigned char sour
switch (cc_mode) { switch (cc_mode) {
case 1: case 1:
target_bitsize = calc_padding_cca(bp, *(cc_width)); target_bitsize = calc_padding_cca(bp, *p_cc_width);
break; break;
case 2: case 2:
target_bitsize = calc_padding_ccb(bp, *(cc_width)); target_bitsize = calc_padding_ccb(bp, *p_cc_width);
break; break;
case 3: case 3:
target_bitsize = calc_padding_ccc(bp, cc_width, linear_width, ecc); target_bitsize = calc_padding_ccc(bp, p_cc_width, linear_width, p_ecc_level);
break; break;
} }
@ -1203,7 +1206,7 @@ static int cc_binary_string(struct zint_symbol *symbol, const unsigned char sour
binary_string[target_bitsize] = '\0'; binary_string[target_bitsize] = '\0';
if (debug_print) { if (debug_print) {
printf("ECC: %d, CC width %d\n", *ecc, *cc_width); printf("ECC: %d, CC width %d\n", *p_ecc_level, *p_cc_width);
printf("Binary: %s (%d)\n", binary_string, target_bitsize); printf("Binary: %s (%d)\n", binary_string, target_bitsize);
} }

View File

@ -1332,7 +1332,7 @@ static int hyphen(const unsigned char *data, int data_len, int offset, int min,
#include "gs1_lint.h" #include "gs1_lint.h"
/* Verify a GS1 input string */ /* Verify a GS1 input string */
INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const int src_len, INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const int length,
unsigned char reduced[]) { unsigned char reduced[]) {
int i, j, last_ai, ai_latch; int i, j, last_ai, ai_latch;
int bracket_level, max_bracket_level, ai_length, max_ai_length, min_ai_length; int bracket_level, max_bracket_level, ai_length, max_ai_length, min_ai_length;
@ -1341,14 +1341,14 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
int error_value = 0; int error_value = 0;
char obracket = symbol->input_mode & GS1PARENS_MODE ? '(' : '['; char obracket = symbol->input_mode & GS1PARENS_MODE ? '(' : '[';
char cbracket = symbol->input_mode & GS1PARENS_MODE ? ')' : ']'; char cbracket = symbol->input_mode & GS1PARENS_MODE ? ')' : ']';
int ai_max = chr_cnt(source, src_len, obracket) + 1; /* Plus 1 so non-zero */ int ai_max = chr_cnt(source, length, obracket) + 1; /* Plus 1 so non-zero */
int *ai_value = (int *) z_alloca(sizeof(int) * ai_max); int *ai_value = (int *) z_alloca(sizeof(int) * ai_max);
int *ai_location = (int *) z_alloca(sizeof(int) * ai_max); int *ai_location = (int *) z_alloca(sizeof(int) * ai_max);
int *data_location = (int *) z_alloca(sizeof(int) * ai_max); int *data_location = (int *) z_alloca(sizeof(int) * ai_max);
int *data_length = (int *) z_alloca(sizeof(int) * ai_max); int *data_length = (int *) z_alloca(sizeof(int) * ai_max);
/* Detect extended ASCII characters */ /* Detect extended ASCII characters */
for (i = 0; i < src_len; i++) { for (i = 0; i < length; i++) {
if (source[i] >= 128) { if (source[i] >= 128) {
strcpy(symbol->errtxt, "250: Extended ASCII characters are not supported by GS1"); strcpy(symbol->errtxt, "250: Extended ASCII characters are not supported by GS1");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
@ -1379,7 +1379,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
max_ai_length = 0; max_ai_length = 0;
min_ai_length = 5; min_ai_length = 5;
ai_latch = 0; ai_latch = 0;
for (i = 0; i < src_len; i++) { for (i = 0; i < length; i++) {
if (source[i] == obracket) { if (source[i] == obracket) {
bracket_level++; bracket_level++;
if (bracket_level > max_bracket_level) { if (bracket_level > max_bracket_level) {
@ -1395,7 +1395,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
min_ai_length = ai_length; min_ai_length = ai_length;
} }
/* Check zero-length AI has data */ /* Check zero-length AI has data */
if (ai_length == 0 && (i + 1 == src_len || source[i + 1] == obracket)) { if (ai_length == 0 && (i + 1 == length || source[i + 1] == obracket)) {
ai_zero_len_no_data = 1; ai_zero_len_no_data = 1;
} else if (ai_length == 1) { } else if (ai_length == 1) {
ai_single_digit = 1; ai_single_digit = 1;
@ -1446,7 +1446,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
if (!(symbol->input_mode & GS1NOCHECK_MODE)) { if (!(symbol->input_mode & GS1NOCHECK_MODE)) {
ai_count = 0; ai_count = 0;
for (i = 1; i < src_len; i++) { for (i = 1; i < length; i++) {
if (source[i - 1] == obracket) { if (source[i - 1] == obracket) {
ai_location[ai_count] = i; ai_location[ai_count] = i;
for (j = 1; source[i + j] != cbracket; j++); for (j = 1; source[i + j] != cbracket; j++);
@ -1465,7 +1465,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
data_location[i] = ai_location[i] + 3; data_location[i] = ai_location[i] + 3;
} }
data_length[i] = 0; data_length[i] = 0;
while ((data_location[i] + data_length[i] < src_len) while ((data_location[i] + data_length[i] < length)
&& (source[data_location[i] + data_length[i]] != obracket)) { && (source[data_location[i] + data_length[i]] != obracket)) {
data_length[i]++; data_length[i]++;
} }
@ -1501,7 +1501,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
/* Resolve AI data - put resulting string in 'reduced' */ /* Resolve AI data - put resulting string in 'reduced' */
j = 0; j = 0;
ai_latch = 1; ai_latch = 1;
for (i = 0; i < src_len; i++) { for (i = 0; i < length; i++) {
if ((source[i] != obracket) && (source[i] != cbracket)) { if ((source[i] != obracket) && (source[i] != cbracket)) {
reduced[j++] = source[i]; reduced[j++] = source[i];
} }
@ -1510,20 +1510,22 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[]
if (ai_latch == 0) { if (ai_latch == 0) {
reduced[j++] = '['; reduced[j++] = '[';
} }
last_ai = to_int(source + i + 1, 2); if (i + 1 != length) {
ai_latch = 0; last_ai = to_int(source + i + 1, 2);
/* The following values from "GS1 General Specifications Release 21.0.1" ai_latch = 0;
Figure 7.8.4-2 "Element strings with predefined length using GS1 Application Identifiers" */ /* The following values from "GS1 General Specifications Release 21.0.1"
if ( Figure 7.8.4-2 "Element strings with predefined length using GS1 Application Identifiers" */
((last_ai >= 0) && (last_ai <= 4)) if (
|| ((last_ai >= 11) && (last_ai <= 20)) ((last_ai >= 0) && (last_ai <= 4))
/* NOTE: as noted by Terry Burton the following complies with ISO/IEC 24724:2011 Table D.1, || ((last_ai >= 11) && (last_ai <= 20))
but clashes with TPX AI [235], introduced May 2019; awaiting feedback from GS1 */ /* NOTE: as noted by Terry Burton the following complies with ISO/IEC 24724:2011 Table D.1,
|| (last_ai == 23) /* legacy support */ /* TODO: probably remove */ but clashes with TPX AI [235], introduced May 2019; awaiting feedback from GS1 */
|| ((last_ai >= 31) && (last_ai <= 36)) || (last_ai == 23) /* legacy support */ /* TODO: probably remove */
|| (last_ai == 41) || ((last_ai >= 31) && (last_ai <= 36))
) { || (last_ai == 41)
ai_latch = 1; ) {
ai_latch = 1;
}
} }
} }
/* The ']' character is simply dropped from the input */ /* The ']' character is simply dropped from the input */

View File

@ -1031,6 +1031,7 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[
symbol->option_3, symbol->scale, symbol->output_options, symbol->fgcolour, symbol->bgcolour, symbol->option_3, symbol->scale, symbol->output_options, symbol->fgcolour, symbol->bgcolour,
seg_count, len > 30 ? "first 30 " : "", seg_count > 1 ? "[0]" : "", len, source, seg_count, len > 30 ? "first 30 " : "", seg_count > 1 ? "[0]" : "", len, source,
primary_len > 30 ? "first 30 " : "", primary_len, primary); primary_len > 30 ? "first 30 " : "", primary_len, primary);
fflush(stdout);
} }
if (total_len > ZINT_MAX_DATA_LEN) { if (total_len > ZINT_MAX_DATA_LEN) {

View File

@ -219,7 +219,7 @@ static int pdf_textprocess_switch(const int curtable, const int newtable, unsign
} }
/* Check consecutive segments for text/num and return the length */ /* Check consecutive segments for text/num and return the length */
static int pdf_text_num_length(int liste[3][PDF_MAX_LEN], const int indexliste, const int start) { static int pdf_text_num_length(short liste[3][PDF_MAX_LEN], const int indexliste, const int start) {
int i, len = 0; int i, len = 0;
for (i = start; i < indexliste; i++) { for (i = start; i < indexliste; i++) {
if (liste[1][i] == PDF_BYT) if (liste[1][i] == PDF_BYT)
@ -289,7 +289,7 @@ static int pdf_text_submode_length(const unsigned char chaine[], const int start
} }
/* Whether to stay in numeric mode or not */ /* Whether to stay in numeric mode or not */
static int pdf_num_stay(const unsigned char *chaine, const int indexliste, int liste[3][PDF_MAX_LEN], const int i) { static int pdf_num_stay(const unsigned char *chaine, const int indexliste, short liste[3][PDF_MAX_LEN], const int i) {
int curtable, not_tex, last_len, last_ml, next_len, num_cws, tex_cws; int curtable, not_tex, last_len, last_ml, next_len, num_cws, tex_cws;
if (liste[0][i] >= 13 || (indexliste == 1 && liste[0][i] > 5)) { if (liste[0][i] >= 13 || (indexliste == 1 && liste[0][i] > 5)) {
@ -320,7 +320,7 @@ static int pdf_num_stay(const unsigned char *chaine, const int indexliste, int l
} }
/* Pack segments using the method described in Appendix D of the AIM specification (ISO/IEC 15438:2015 Annex N) */ /* Pack segments using the method described in Appendix D of the AIM specification (ISO/IEC 15438:2015 Annex N) */
static void pdf_appendix_d_encode(const unsigned char *chaine, int liste[3][PDF_MAX_LEN], int *p_indexliste, static void pdf_appendix_d_encode(const unsigned char *chaine, short liste[3][PDF_MAX_LEN], int *p_indexliste,
const int debug_print) { const int debug_print) {
const int indexliste = *p_indexliste; const int indexliste = *p_indexliste;
int i = 0, next, last = 0, stayintext = 0; int i = 0, next, last = 0, stayintext = 0;
@ -496,7 +496,7 @@ static void pdf_textprocess(short *chainemc, int *p_mclength, const unsigned cha
/* Minimal text compaction */ /* Minimal text compaction */
static void pdf_textprocess_minimal(short *chainemc, int *p_mclength, const unsigned char chaine[], static void pdf_textprocess_minimal(short *chainemc, int *p_mclength, const unsigned char chaine[],
int liste[3][PDF_MAX_LEN], const int indexliste, const int lastmode, const int is_last_seg, short liste[3][PDF_MAX_LEN], const int indexliste, const int lastmode, const int is_last_seg,
int *p_curtable, int *p_tex_padded, int *p_i) { int *p_curtable, int *p_tex_padded, int *p_i) {
const int real_lastmode = PDF_REAL_MODE(lastmode); const int real_lastmode = PDF_REAL_MODE(lastmode);
int i, j, k; int i, j, k;
@ -913,7 +913,7 @@ static void pdf_addEdges(const unsigned char source[], const int length, const i
} }
/* Calculate optimized encoding modes */ /* Calculate optimized encoding modes */
static int pdf_define_mode(int liste[3][PDF_MAX_LEN], int *p_indexliste, const unsigned char source[], static int pdf_define_mode(short liste[3][PDF_MAX_LEN], int *p_indexliste, const unsigned char source[],
const int length, const int lastmode, const int debug_print) { const int length, const int lastmode, const int debug_print) {
int i, j, v_i; int i, j, v_i;
@ -980,9 +980,9 @@ static int pdf_define_mode(int liste[3][PDF_MAX_LEN], int *p_indexliste, const u
} }
*p_indexliste = length - mode_start; *p_indexliste = length - mode_start;
if (mode_start) { if (mode_start) {
memmove(liste[0], liste[0] + mode_start, sizeof(int) * (*p_indexliste)); memmove(liste[0], liste[0] + mode_start, sizeof(short) * (*p_indexliste));
memmove(liste[1], liste[1] + mode_start, sizeof(int) * (*p_indexliste)); memmove(liste[1], liste[1] + mode_start, sizeof(short) * (*p_indexliste));
memmove(liste[2], liste[2] + mode_start, sizeof(int) * (*p_indexliste)); memmove(liste[2], liste[2] + mode_start, sizeof(short) * (*p_indexliste));
} }
if (debug_print) { if (debug_print) {
printf("modes (%d):", *p_indexliste); printf("modes (%d):", *p_indexliste);
@ -1000,7 +1000,7 @@ static int pdf_initial(struct zint_symbol *symbol, const unsigned char chaine[],
const int is_micro, const int is_last_seg, int *p_lastmode, int *p_curtable, int *p_tex_padded, const int is_micro, const int is_last_seg, int *p_lastmode, int *p_curtable, int *p_tex_padded,
short chainemc[PDF_MAX_STREAM_LEN], int *p_mclength) { short chainemc[PDF_MAX_STREAM_LEN], int *p_mclength) {
int i, indexchaine = 0, indexliste = 0; int i, indexchaine = 0, indexliste = 0;
int liste[3][PDF_MAX_LEN] = {{0}}; short liste[3][PDF_MAX_LEN] = {{0}};
int mclength; int mclength;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
const int fast_encode = symbol->input_mode & FAST_MODE; const int fast_encode = symbol->input_mode & FAST_MODE;

View File

@ -183,18 +183,20 @@ static void test_large(const testCtx *const p_ctx) {
/*133*/ { -1, 10, { 0, 0, "" }, "\\", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, /*133*/ { -1, 10, { 0, 0, "" }, "\\", 39, ZINT_ERROR_TOO_LONG, -1, -1 },
/*134*/ { -1, 10, { 0, 0, "" }, "\200", 36, 0, 16, 49 }, /*134*/ { -1, 10, { 0, 0, "" }, "\200", 36, 0, 16, 49 },
/*135*/ { -1, 10, { 0, 0, "" }, "\200", 37, ZINT_ERROR_TOO_LONG, -1, -1 }, /*135*/ { -1, 10, { 0, 0, "" }, "\200", 37, ZINT_ERROR_TOO_LONG, -1, -1 },
/*136*/ { 3, 10, { 0, 0, "" }, "A", 46, 0, 16, 49 }, /* Version T-48 with ECI (9 less as PAD escape char + "\123456") */ /*136*/ { -1, 10, { 0, 0, "" }, "AAA\200", 31, 0, 16, 49 }, /* ASCII + BYTE (ASCII UpSh - worse than BYTE) */
/*137*/ { 3, 10, { 0, 0, "" }, "A", 47, ZINT_ERROR_TOO_LONG, -1, -1 }, /*137*/ { -1, 10, { 0, 0, "" }, "AAA\200", 32, ZINT_ERROR_TOO_LONG, -1, -1 },
/*138*/ { 3, 10, { 0, 0, "" }, "\001", 32, 0, 16, 49 }, /*138*/ { 3, 10, { 0, 0, "" }, "A", 46, 0, 16, 49 }, /* Version T-48 with ECI (9 less as PAD escape char + "\123456") */
/*139*/ { 3, 10, { 0, 0, "" }, "\001", 33, ZINT_ERROR_TOO_LONG, -1, -1 }, /*139*/ { 3, 10, { 0, 0, "" }, "A", 47, ZINT_ERROR_TOO_LONG, -1, -1 },
/*140*/ { 3, 10, { 0, 0, "" }, "\001", 32, 0, 16, 49 },
/*141*/ { 3, 10, { 0, 0, "" }, "\001", 33, ZINT_ERROR_TOO_LONG, -1, -1 },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol = NULL;
char data_buf[4096]; char data_buf[4096];
testStart("test_large"); testStartSymbol("test_large", &symbol);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -282,9 +284,9 @@ static void test_input(const testCtx *const p_ctx) {
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol = NULL;
testStart("test_input"); testStartSymbol("test_input", &symbol);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -2879,7 +2881,7 @@ static void test_encode(const testCtx *const p_ctx) {
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol = NULL;
char escaped[8192]; char escaped[8192];
char bwipp_buf[32768]; char bwipp_buf[32768];
@ -2887,7 +2889,7 @@ static void test_encode(const testCtx *const p_ctx) {
int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */ int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
testStart("test_encode"); testStartSymbol("test_encode", &symbol);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -3268,7 +3270,7 @@ static void test_encode_segs(const testCtx *const p_ctx) {
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, j, seg_count, ret; int i, j, seg_count, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol = NULL;
char escaped[8192]; char escaped[8192];
char bwipp_buf[32768]; char bwipp_buf[32768];
@ -3276,7 +3278,7 @@ static void test_encode_segs(const testCtx *const p_ctx) {
int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */ int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
testStart("test_encode_segs"); testStartSymbol("test_encode_segs", &symbol);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -3364,9 +3366,10 @@ static void test_fuzz(const testCtx *const p_ctx) {
struct item data[] = { struct item data[] = {
/* 0*/ { -1, "3333P33B\035333V3333333333333\0363", -1, 0, 1, "" }, /* #181 Nico Gunkel, OSS-Fuzz */ /* 0*/ { -1, "3333P33B\035333V3333333333333\0363", -1, 0, 1, "" }, /* #181 Nico Gunkel, OSS-Fuzz */
/* 1*/ { -1, "{{-06\024755712162106130000000829203983\377", -1, 0, 1, "" }, /* #232 Jan Schrewe, CI-Fuzz, out-of-bounds in is_last_single_ascii() sp + 1 */ /* 1*/ { -1, "{{-06\024755712162106130000000829203983\377", -1, 0, 1, "" }, /* #232 Jan Schrewe, CI-Fuzz, out-of-bounds in is_last_single_ascii() sp + 1 */
/* 2*/ { -1, "\000\000\000\367\000\000\000\000\000\103\040\000\000\244\137\140\140\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\165\060\060\060\060\061\060\060\114\114\060\010\102\102\102\102\102\102\102\102\057\102\100\102\057\233\100\102", 60, 0, 1, "" }, /* #300 (#4) Andre Maute */ /* 2*/ { -1, "\000\000\000\367\000\000\000\000\000\103\040\000\000\244\137\140\140\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\165\060\060\060\060\061\060\060\114\114\060\010\102\102\102\102\102\102\102\102\057\102\100\102\057\233\100\102", 60, 0, 1, "" }, /* #300 (#4) Andre Maute (`c1_c40text_cnt()` not accounting for extended ASCII shifts) */
/* 3*/ { 10, "\153\153\153\060\001\000\134\153\153\015\015\353\362\015\015\015\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\362\362\000", 65, ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#8) Andre Maute */ /* 3*/ { 10, "\153\153\153\060\001\000\134\153\153\015\015\353\362\015\015\015\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\362\362\000", 65, ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#8) Andre Maute (`c1_encode()` looping on latch) */
/* 4*/ { 10, "\015\015\353\362\015\015\015\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\362\362\000", 39, 0, 1, "" }, /* #300 (#8 shortened) Andre Maute */ /* 4*/ { 10, "\015\015\353\362\015\015\015\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\362\362\000", 39, 0, 1, "" }, /* #300 (#8 shortened) Andre Maute */
/* 5*/ { 10, "\153\153\153\153\153\060\001\000\000\134\153\153\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\153\153\153\153\153\153\043\000\000\307\000\147\000\000\000\043\113\153\162\162\215\220", 90, ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#12) Andre Maute (too small buffer for Version T) */
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;

View File

@ -3464,25 +3464,37 @@ static void test_fuzz(const testCtx *const p_ctx) {
struct item { struct item {
int symbology; int symbology;
int input_mode; int input_mode;
int option_1;
char *data; char *data;
int length; int length;
char *composite; char *composite;
int ret; int ret;
int bwipp_cmp;
char *comment;
}; };
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_EANX_CC, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG }, /* 0*/ { BARCODE_EANX_CC, -1, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG, 1, "" },
/* 1*/ { BARCODE_UPCA_CC, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG }, /* 1*/ { BARCODE_UPCA_CC, -1, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG , 1, ""},
/* 2*/ { BARCODE_UPCE_CC, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG }, /* 2*/ { BARCODE_UPCE_CC, -1, -1, "+123456789012345678", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG , 1, ""},
/* 3*/ { BARCODE_EANX_CC, -1, "+12345", -1, "[21]A12345678", 0 }, /* 3*/ { BARCODE_EANX_CC, -1, -1, "+12345", -1, "[21]A12345678", 0 , 0, "BWIPP checks for proper EAN data"},
/* 4*/ { BARCODE_EANX_CC, -1, "+123456", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG }, /* 4*/ { BARCODE_EANX_CC, -1, -1, "+123456", -1, "[21]A12345678", ZINT_ERROR_TOO_LONG, 1, "" },
/* 5*/ { BARCODE_EANX_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, "kks", -1, "()111%", ZINT_ERROR_INVALID_DATA }, /* #300 (#5), Andre Maute */ /* 5*/ { BARCODE_EANX_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "kks", -1, "()111%", ZINT_ERROR_INVALID_DATA, 1, "" }, /* #300 (#5), Andre Maute (`dbar_date()` not checking length + other non-checks) */
/* 6*/ { BARCODE_UPCA_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, "\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\225\215\153\153\153\153\153\153\263\153\153\153\153\153\153\153\153\153\153\163", -1, "()90", ZINT_ERROR_TOO_LONG }, /* #300 (#6), Andre Maute */ /* 6*/ { BARCODE_UPCA_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\225\215\153\153\153\153\153\153\263\153\153\153\153\153\153\153\153\153\153\163", -1, "()90", ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#6), Andre Maute (`dbar_date()` not checking length + other non-checks) */
/* 7*/ { BARCODE_UPCA_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\225\215\153\153\153\153\153\153\263\153\153\377\002\000\000\153\153\153\153\163\000\000\000\153\153\153\153\153\153\153\060\047\047\043\047\057\153\153\153\153\153\000\000\000\000\153\153\153\161\153\153\153\153\153\153\153\153\153\153\153\153\153\167\167\167\167\167\167\167\167\167\167\167\167\167\167\167\167\001\100\000\000\000\000\000\000\000\167\167\167\167\167\167\167\167\167\167\167\167\167\167", 127, "()904OOOOO)CK0336680OOOOOOOOOOOOOO29[0kkkk%%%%(", ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#11), Andre Maute (`gs1_verify()` not checking length on resolve AI data loop) */
/* 8*/ { BARCODE_EANX_CC, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\153\225\215\153\153\153\153\153\153\263\153\153\377\002\000\000\153\153\153\153\163\000\000\000\153\153\153\153\153\153\153\060\047\047\043\047\057\153\153\153\153\153\000\000\000\000\153\153\153\161\153\153\153\153\153\153\153\153\153\153\153\153\153\167\167\167\167\167\167\167\167\167\167\167\167\167\167\167\167\001\100\000\000\000\000\000\000\000\167\167\167\167\167\167\167\167\167\167\167\167\167\167", 127, "()904OOOOO)CK0336680OOOOOOOOOOOOOO29[0kkkk%%%%(", ZINT_ERROR_TOO_LONG, 1, "" }, /* #300 (#11 with EANX_CC) */
/* 9*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, 3, "[]28", -1, "[]RRR___________________KKKRRR0000", 0, 1, "" }, /* #300 (#13), Andre Maute (`calc_padding_ccc()` dividing by zero when linear width == 68) */
/*10*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, 3, "[]2", -1, "[]RRR___________________KKKRRR0000", 0, 1, "" }, /* #300 (#13 shortened to min linear input (but same linear width 68)) */
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, composite_length, ret; int i, length, composite_length, ret;
struct zint_symbol *symbol = NULL; struct zint_symbol *symbol = NULL;
char bwipp_buf[32768];
char bwipp_msg[1024];
int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
testStartSymbol("test_fuzz", &symbol); testStartSymbol("test_fuzz", &symbol);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -3492,7 +3504,7 @@ static void test_fuzz(const testCtx *const p_ctx) {
symbol = ZBarcode_Create(); symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n"); assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
assert_zero(length >= 128, "i:%d length %d >= 128\n", i, length); assert_zero(length >= 128, "i:%d length %d >= 128\n", i, length);
strcpy(symbol->primary, data[i].data); strcpy(symbol->primary, data[i].data);
@ -3501,6 +3513,23 @@ static void test_fuzz(const testCtx *const p_ctx) {
ret = ZBarcode_Encode(symbol, (const unsigned char *) data[i].composite, composite_length); ret = ZBarcode_Encode(symbol, (const unsigned char *) data[i].composite, composite_length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (ret < ZINT_ERROR) {
if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) {
if (!data[i].bwipp_cmp) {
if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment);
} else {
char modules_dump[32768];
assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i);
ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL);
assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, modules_dump);
assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, modules_dump);
}
}
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -5356,7 +5356,7 @@ static void test_fuzz(const testCtx *const p_ctx) {
"\000\000\000\000\000\000\000\000\323\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" "\000\000\000\000\000\000\000\000\323\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000", "\000\000\000\000\000\000\000\000",
1048, 0, 0, "BWIPP different encodation" 1048, 0, 0, "BWIPP different encodation"
}, /* #300 (#1) Andre Maute */ }, /* #300 (#1) Andre Maute (`pdf_text_submode_length()` not checking if previous/next BYT) */
/* 29*/ { BARCODE_PDF417, DATA_MODE | FAST_MODE, -1, -1, /* 29*/ { BARCODE_PDF417, DATA_MODE | FAST_MODE, -1, -1,
"\060\060\060\060\060\060\060\060\060\060\060\162\162\162\162\162\162\162\162\162\162\047\122\162\000\000\167\211\206\001\000\047\153\153\153\153\153\067\066\164" "\060\060\060\060\060\060\060\060\060\060\060\162\162\162\162\162\162\162\162\162\162\047\122\162\000\000\167\211\206\001\000\047\153\153\153\153\153\067\066\164"
"\060\060\060\060\060\060\060\060\060\060\060\162\162\162\162\162\162\162\162\162\162\047\122\162\000\000\167\211\206\001\000\047\153\153\153\153\153\153\153\164" "\060\060\060\060\060\060\060\060\060\060\060\162\162\162\162\162\162\162\162\162\162\047\122\162\000\000\167\211\206\001\000\047\153\153\153\153\153\153\153\164"

View File

@ -55,13 +55,13 @@ foreach ($lines as $line) {
if ($line === '' || $line[0] === '#') { if ($line === '' || $line[0] === '#') {
continue; continue;
} }
if (!preg_match('/^([0-9]+(?:-[0-9]+)?) +([ *] )([NXYZ][0-9.][ NXYZ0-9.,a-z=|\[\]]*)(?:# (.+))?$/', $line, $matches)) { if (!preg_match('/^([0-9]+(?:-[0-9]+)?) +([ *] )([NXYZ][0-9.][ NXYZ0-9.,a-z=|+\[\]]*)(?:# (.+))?$/', $line, $matches)) {
print $line . PHP_EOL; print $line . PHP_EOL;
exit("$basename:" . __LINE__ . " ERROR: Could not parse line $line_no" . PHP_EOL); exit("$basename:" . __LINE__ . " ERROR: Could not parse line $line_no" . PHP_EOL);
} }
$ai = $matches[1]; $ai = $matches[1];
$fixed = trim($matches[2]); $fixed = trim($matches[2]);
$spec = preg_replace('/ +req=[0-9,n]*/', '', trim($matches[3])); // Strip mandatory association info $spec = preg_replace('/ +req=[0-9,n+]*/', '', trim($matches[3])); // Strip mandatory association info
$spec = preg_replace('/ +ex=[0-9,n]*/', '', $spec); // Strip invalid pairings info $spec = preg_replace('/ +ex=[0-9,n]*/', '', $spec); // Strip invalid pairings info
$spec = preg_replace('/ +dlpkey[=0-9,|]*/', '', $spec); // Strip Digital Link primary key info $spec = preg_replace('/ +dlpkey[=0-9,|]*/', '', $spec); // Strip Digital Link primary key info
$comment = isset($matches[4]) ? trim($matches[4]) : ''; $comment = isset($matches[4]) ? trim($matches[4]) : '';