From d56c7915b79f87e8577e9575170c9914d63b629c Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 28 Mar 2020 02:50:15 +0000 Subject: [PATCH] #181 OSS-Fuzz MAXICODE fix, prevent index overrun on numeric compaction --- backend/maxicode.c | 11 ++++---- backend/tests/test_maxicode.c | 53 +++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/backend/maxicode.c b/backend/maxicode.c index 52b384b0..cf7200fe 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2010-2017 Robin Stuart + Copyright (C) 2010-2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -36,7 +36,6 @@ #include "maxicode.h" #include "reedsol.h" #include -#include 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 */ count = 0; - for (i = j; i < 143; i++) { + for (i = j; i < 144; i++) { if ((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) { /* Character is a number */ count++; @@ -426,7 +425,7 @@ static int maxi_text_process(int mode, unsigned char source[], int length, int e do { if (set[i] == 6) { /* Number compression */ - char substring[11]; + char substring[10]; int value; 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); i += 6; - for (j = i; j < 140; j++) { + for (j = i; j < 141; j++) { set[j] = set[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 { i++; } - } while (i <= 143); + } while (i <= 135); /* 144 - 9 */ /* Insert ECI at the beginning of message if needed */ /* Encode ECI assignment numbers according to table 3 */ diff --git a/backend/tests/test_maxicode.c b/backend/tests/test_maxicode.c index 740c3673..f8a9117a 100644 --- a/backend/tests/test_maxicode.c +++ b/backend/tests/test_maxicode.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2019 Robin Stuart + Copyright (C) 2008-2020 Robin Stuart Redistribution and use in source and binary forms, with or without 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 SUCH DAMAGE. */ +/* vim: set ts=4 sw=4 et : */ -#include -#include -#include #include "testcommon.h" -//#define TEST_GENERATE_EXPECTED 1 +//#define TEST_BEST_SUPPORTED_SET_GENERATE_EXPECTED 1 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); 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", 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); @@ -130,9 +128,52 @@ static void test_best_supported_set(void) 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() { test_best_supported_set(); + test_fuzz(); testReport();