#181 OSS-Fuzz MAXICODE fix, prevent index overrun on numeric compaction

This commit is contained in:
gitlost 2020-03-28 02:50:15 +00:00
parent 0f5deccfb6
commit d56c7915b7
2 changed files with 52 additions and 12 deletions

View File

@ -2,7 +2,7 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2010-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2010-2020 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -36,7 +36,6 @@
#include "maxicode.h" #include "maxicode.h"
#include "reedsol.h" #include "reedsol.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
static int maxi_codeword[144]; static int maxi_codeword[144];
@ -294,7 +293,7 @@ static int maxi_text_process(int mode, unsigned char source[], int length, int e
} }
/* Number compression not allowed in primary message */ /* Number compression not allowed in primary message */
count = 0; count = 0;
for (i = j; i < 143; i++) { for (i = j; i < 144; i++) {
if ((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) { if ((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) {
/* Character is a number */ /* Character is a number */
count++; count++;
@ -426,7 +425,7 @@ static int maxi_text_process(int mode, unsigned char source[], int length, int e
do { do {
if (set[i] == 6) { if (set[i] == 6) {
/* Number compression */ /* Number compression */
char substring[11]; char substring[10];
int value; int value;
for (j = 0; j < 9; j++) { for (j = 0; j < 9; j++) {
@ -443,7 +442,7 @@ static int maxi_text_process(int mode, unsigned char source[], int length, int e
character[i + 5] = (value & 0x3f); character[i + 5] = (value & 0x3f);
i += 6; i += 6;
for (j = i; j < 140; j++) { for (j = i; j < 141; j++) {
set[j] = set[j + 3]; set[j] = set[j + 3];
character[j] = character[j + 3]; character[j] = character[j + 3];
} }
@ -451,7 +450,7 @@ static int maxi_text_process(int mode, unsigned char source[], int length, int e
} else { } else {
i++; i++;
} }
} while (i <= 143); } while (i <= 135); /* 144 - 9 */
/* Insert ECI at the beginning of message if needed */ /* Insert ECI at the beginning of message if needed */
/* Encode ECI assignment numbers according to table 3 */ /* Encode ECI assignment numbers according to table 3 */

View File

@ -1,6 +1,6 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2008-2019 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2008-2020 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -27,13 +27,11 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
/* vim: set ts=4 sw=4 et : */
#include <stdio.h>
#include <string.h>
#include <zint.h>
#include "testcommon.h" #include "testcommon.h"
//#define TEST_GENERATE_EXPECTED 1 //#define TEST_BEST_SUPPORTED_SET_GENERATE_EXPECTED 1
static void test_best_supported_set(void) static void test_best_supported_set(void)
{ {
@ -105,7 +103,7 @@ static void test_best_supported_set(void)
ret = ZBarcode_Encode(symbol, data[i].data, length); ret = ZBarcode_Encode(symbol, data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret);
#ifdef TEST_GENERATE_EXPECTED #ifdef TEST_BEST_SUPPORTED_SET_GENERATE_EXPECTED
printf(" /*%2d*/ { %s, \"%s\", %d, %.0f, %.0f, %d, %d, %d, \"%s\",\n", printf(" /*%2d*/ { %s, \"%s\", %d, %.0f, %.0f, %d, %d, %d, \"%s\",\n",
i, testUtilBarcodeName(data[i].symbology), testUtilEscape(data[i].data, length, escaped_data, sizeof(escaped_data)), ret, i, testUtilBarcodeName(data[i].symbology), testUtilEscape(data[i].data, length, escaped_data, sizeof(escaped_data)), ret,
data[i].w, data[i].h, data[i].ret_vector, symbol->rows, symbol->width, data[i].comment); data[i].w, data[i].h, data[i].ret_vector, symbol->rows, symbol->width, data[i].comment);
@ -130,9 +128,52 @@ static void test_best_supported_set(void)
testFinish(); testFinish();
} }
// #181 Nico Gunkel OSS-Fuzz
static void test_fuzz(void)
{
testStart("");
int ret;
struct item {
int symbology;
unsigned char* data;
int length;
int ret;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%2d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { BARCODE_MAXICODE, "\223\223\223\223\223\200\000\060\060\020\122\104\060\343\000\000\040\104\104\104\104\177\377\040\000\324\336\000\000\000\000\104\060\060\060\060\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\104\060\104\104\000\000\000\040\104\104\104\104\177\377\377\377\324\336\000\000\000\000\104\377\104\001\104\104\104\104\104\104\233\233\060\060\060\060\060\060\060\060\060\325\074", 107, ZINT_ERROR_TOO_LONG }, // Original OSS-Fuzz triggering data
/* 1*/ { BARCODE_MAXICODE, "AaAaAaAaAaAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA123456789", -1, ZINT_ERROR_TOO_LONG }, // Add 6 lowercase a's so 6 SHIFTS inserted so 6 + 138 (max input len) = 144 and numbers come at end of buffer
/* 2*/ { BARCODE_MAXICODE, "AaAaAaAaAaAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA123456789A", -1, ZINT_ERROR_TOO_LONG },
/* 3*/ { BARCODE_MAXICODE, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1, ZINT_ERROR_TOO_LONG }, // First 6 chars ignored for number compaction so max numeric digits appears to be 135 not 138 (for mode 4 anyway) TODO: investigate further
/* 4*/ { BARCODE_MAXICODE, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345", -1, 0 },
};
int data_size = sizeof(data) / sizeof(struct item);
for (int i = 0; i < data_size; i++) {
struct zint_symbol* symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = data[i].symbology;
int length = data[i].length;
if (length == -1) {
length = strlen(data[i].data);
}
ret = ZBarcode_Encode(symbol, data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
ZBarcode_Delete(symbol);
}
testFinish();
}
int main() int main()
{ {
test_best_supported_set(); test_best_supported_set();
test_fuzz();
testReport(); testReport();