1
0
mirror of https://git.code.sf.net/p/zint/code synced 2025-12-24 05:17:05 +00:00

AZTEC: fix another out-of-bounds crash when user-specified size given

ticket #300 (no. 3), props Andre Maute
This commit is contained in:
gitlost
2023-11-24 10:30:57 +00:00
parent 7c4a538248
commit 86748999a4
2 changed files with 129 additions and 49 deletions

View File

@@ -839,8 +839,43 @@ static void az_populate_map(short AztecMap[], const int layers) {
}
}
/* Helper to insert dummy '0' or '1's into runs of same bits. See ISO/IEC 24778:2008 7.3.1.2 */
static int az_bitrun_stuff(const char *binary_string, const int data_length, const int codeword_size,
char adjusted_string[AZTEC_MAX_CAPACITY]) {
int i, j = 0, count = 0;
for (i = 0; i < data_length; i++) {
if ((j + 1) % codeword_size == 0) {
/* Last bit of codeword */
/* 7.3.1.2 "whenever the first B-1 bits ... are all “0”s, then a dummy “1” is inserted..."
"Similarly a message codeword that starts with B-1 “1”s has a dummy “0” inserted..." */
if (count == 0 || count == (codeword_size - 1)) {
/* Codeword of B-1 '0's or B-1 '1's */
if (j >= AZTEC_MAX_CAPACITY) {
return 0; /* Fail */
}
adjusted_string[j++] = count == 0 ? '1' : '0';
count = binary_string[i] == '1' ? 1 : 0;
} else {
count = 0;
}
} else if (binary_string[i] == '1') { /* Skip B so only counting B-1 */
count++;
}
if (j >= AZTEC_MAX_CAPACITY) {
return 0; /* Fail */
}
adjusted_string[j++] = binary_string[i];
}
return j;
}
INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
int x, y, i, j, p, data_blocks, ecc_blocks, layers, total_bits;
int x, y, i, p, data_blocks, ecc_blocks, layers, total_bits;
char bit_pattern[AZTEC_MAP_POSN_MAX + 1]; /* Note AZTEC_MAP_POSN_MAX > AZTEC_BIN_CAPACITY */
/* To lessen stack usage, share binary_string buffer with bit_pattern, as accessed separately */
char *binary_string = bit_pattern;
@@ -1024,31 +1059,11 @@ INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int
codeword_size = 12;
}
j = 0;
count = 0;
for (i = 0; i < data_length; i++) {
if ((j + 1) % codeword_size == 0) {
/* Last bit of codeword */
/* 7.3.1.2 "whenever the first B-1 bits ... are all “0”s, then a dummy “1” is inserted..."
"Similarly a message codeword that starts with B-1 “1”s has a dummy “0” inserted..." */
if (count == 0 || count == (codeword_size - 1)) {
/* Codeword of B-1 '0's or B-1 '1's */
adjusted_string[j] = count == 0 ? '1' : '0';
j++;
count = binary_string[i] == '1' ? 1 : 0;
} else {
count = 0;
}
} else if (binary_string[i] == '1') { /* Skip B so only counting B-1 */
count++;
}
adjusted_string[j] = binary_string[i];
j++;
adjusted_length = az_bitrun_stuff(binary_string, data_length, codeword_size, adjusted_string);
if (adjusted_length == 0) {
strcpy(symbol->errtxt, "705: Data too long for specified Aztec Code symbol size");
return ZINT_ERROR_TOO_LONG;
}
adjusted_length = j;
adjustment_size = adjusted_length - data_length;
/* Add padding */
@@ -1107,31 +1122,11 @@ INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int
codeword_size = 12;
}
j = 0;
count = 0;
for (i = 0; i < data_length; i++) {
if ((j + 1) % codeword_size == 0) {
/* Last bit of codeword */
if (count == 0 || count == (codeword_size - 1)) {
/* Codeword of B-1 '0's or B-1 '1's */
if (j + 1 >= AZTEC_MAX_CAPACITY) {
strcpy(symbol->errtxt, "704: Data too long for specified Aztec Code symbol size");
return ZINT_ERROR_TOO_LONG;
}
adjusted_string[j++] = count == 0 ? '1' : '0';
count = binary_string[i] == '1' ? 1 : 0;
} else {
count = 0;
}
} else if (binary_string[i] == '1') { /* Skip B so only counting B-1 */
count++;
}
adjusted_string[j++] = binary_string[i];
adjusted_length = az_bitrun_stuff(binary_string, data_length, codeword_size, adjusted_string);
if (adjusted_length == 0) {
strcpy(symbol->errtxt, "704: Data too long for specified Aztec Code symbol size");
return ZINT_ERROR_TOO_LONG;
}
adjusted_length = j;
remainder = adjusted_length % codeword_size;