From bee8794cdaa865730997fd9782bdb220e9c1c62c Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 25 Mar 2020 22:31:59 +0000 Subject: [PATCH] #181 OSS-Fuzz DOTCODE fix, check length before accessing in binary() --- backend/dotcode.c | 22 ++++++----- backend/tests/CMakeLists.txt | 1 + backend/tests/test_dotcode.c | 74 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 backend/tests/test_dotcode.c diff --git a/backend/dotcode.c b/backend/dotcode.c index 877ee008..64848276 100644 --- a/backend/dotcode.c +++ b/backend/dotcode.c @@ -104,7 +104,7 @@ static int clr_row(char *Dots, const int Hgt, const int Wid, const int y) { } /* Dot pattern scoring routine from Annex A */ -static const int score_array(char Dots[], int Hgt, int Wid) { +static int score_array(char Dots[], int Hgt, int Wid) { int x, y, worstedge, first, last, sum; int penalty_local = 0; int penalty = 0; @@ -441,10 +441,10 @@ static int ahead_b(const unsigned char source[], int position, int length) { } /* checks if the next character is in the range 128 to 255 (Annex F.II.I) */ -static int binary(const unsigned char source[], int position) { +static int binary(const unsigned char source[], int length, int position) { int retval = 0; - if (source[position] >= 128) { + if (position < length && source[position] >= 128) { retval = 1; } @@ -669,7 +669,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha /* Step B3 */ if ((!done) && (encoding_mode == 'C')) { - if (binary(source, input_position)) { + if (binary(source, length, input_position)) { if (n_digits(source, input_position + 1, length) > 0) { if ((source[input_position] - 128) < 32) { codeword_array[array_length] = 110; // Bin Shift A @@ -805,7 +805,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha /* Step C3 */ if ((!done) && (encoding_mode == 'B')) { - if (binary(source, input_position)) { + if (binary(source, length, input_position)) { if (datum_b(source, input_position + 1, length)) { if ((source[input_position] - 128) < 32) { codeword_array[array_length] = 110; // Bin Shift A @@ -907,7 +907,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha /* Step D3 */ if ((!done) && (encoding_mode == 'A')) { - if (binary(source, input_position)) { + if (binary(source, length, input_position)) { if (datum_a(source, input_position + 1, length)) { if ((source[input_position] - 128) < 32) { codeword_array[array_length] = 110; // Bin Shift A @@ -1000,10 +1000,10 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha * base 103 into five base 259 values..." */ if ((!done) && (encoding_mode == 'X')) { - if (binary(source, input_position) - || binary(source, input_position + 1) - || binary(source, input_position + 2) - || binary(source, input_position + 3)) { + if (binary(source, length, input_position) + || binary(source, length, input_position + 1) + || binary(source, length, input_position + 2) + || binary(source, length, input_position + 3)) { binary_buffer *= 259; binary_buffer += source[input_position]; binary_buffer_size++; @@ -1213,6 +1213,8 @@ static void apply_mask(int mask, int data_length, unsigned char *masked_codeword int weight = 0; int j; + (void)dot_stream; /* Not currently used */ + switch (mask) { case 0: masked_codeword_array[0] = 0; diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index b84374eb..e416a171 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -56,6 +56,7 @@ zint_add_test(codablock, test_codablock) zint_add_test(common, test_common) zint_add_test(composite, test_composite) zint_add_test(dmatrix, test_dmatrix) +zint_add_test(dotcode, test_dotcode) zint_add_test(eci, test_eci) zint_add_test(gb18030, test_gb18030) zint_add_test(gb2312, test_gb2312) diff --git a/backend/tests/test_dotcode.c b/backend/tests/test_dotcode.c new file mode 100644 index 00000000..6120c1c5 --- /dev/null +++ b/backend/tests/test_dotcode.c @@ -0,0 +1,74 @@ +/* + libzint - the open source barcode library + 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 + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include "testcommon.h" + +// #181 Christian Hartlage OSS-Fuzz +static void test_fuzz(void) +{ + testStart(""); + + int ret; + struct item { + unsigned char* data; + int ret; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "(\207'", 0 }, // 0x28,0x87,0x27 Note: should but doesn't trigger sanitize error if no length check, for some reason; TODO: determine why + }; + 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 = BARCODE_DOTCODE; + int 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_fuzz(); + + testReport(); + + return 0; +}