Hi,
I set up fuzzing for the barcode generation and found a few bugs in different barcode generations. This Ticket is focussing on the EAN creation, because only a few ASCII characters input are enough to trigger the bug.
You can either input "55++15" into the qt-ui or use my reproducer.
This little reprocuder triggers the bug:
#include <zint.h> #include <string> int main() { std::string input = "55++15"; struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create(); my_symbol->symbology = BARCODE_EANX; ZBarcode_Encode_and_Buffer(my_symbol, (unsigned char *) input.c_str(), input.size() , 0); ZBarcode_Delete(my_symbol); return 0; }
Link against the current libzint.so as generated by cmake and the segfault will occur.
When compiled with address sanitizer, the following stacktrace will be printed:
/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24: runtime error: index -1 out of bounds for type 'const char *[4]' SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24 in /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24: runtime error: null pointer passed as argument 2, which is declared to never be null /usr/include/string.h:122:14: note: nonnull attribute specified here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24 in AddressSanitizer:DEADLYSIGNAL ================================================================= ==18211==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f77850ea5a1 bp 0x7ffe4ef2c1f0 sp 0x7ffe4ef2b9a8 T0) ==18211==The signal is caused by a READ memory access. ==18211==Hint: address points to the zero page. #0 0x7f77850ea5a0 /build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59 #1 0x47edaf in strcpy /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:429:22 #2 0x7f7786599893 in add_on /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:9 #3 0x7f77865971cb in eanx /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:881:13 #4 0x7f7786554046 in reduced_charset /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c #5 0x7f7786549e1b in ZBarcode_Encode /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c:1205:20 #6 0x7f778655228f in ZBarcode_Encode_and_Buffer /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c:1392:20 #7 0x4c57c2 in main (/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/demo/poc+0x4c57c2) #8 0x7f7784f7db96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 #9 0x41b6b9 in _start (/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/demo/poc+0x41b6b9)
I will create bug reports for the other barcodes when I have some time in the next days. In order to trigger them the input needs to contain some non-printable characters so I don't think they are as significant as the EAN one.
Affected barcodes are AUSPOST family, CODEONE, DOTCODE, VIN and CODABLOCKF
Best regards,
Chris
Hi Chris,
Thank you for finding this and taking the time to let us know. I have added a check to the UPC/EAN code to throw an error if more than one + character is included in the input data.
I look forward to seeing what else you find!
Robin.
Hi Robin,
Another bug, that I found in the Australian Post family of barcodes can be triggered when inputting the following byte sequence:
0x41 0x00 0x00 0x00, an uppercase A followed by 3 null bytes. This will lead to a heap buffer read overflow:If you want to support OSS-Fuzz integration, the static libary version needs to be integrated by you. For better conforming OSS-Fuzz rules you could also check in the fuzz target at a fitting location in the project itself (like libpng is doing here: https://github.com/glennrp/libpng/tree/libpng16/contrib/oss-fuzz).
Zint might even be eligible for an integration reward by Google: https://opensource.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html
But I don't know exactly how they deem projects to be eligible.
Best regards,
Chris
Last edit: Christian Hartlage 2022-03-23
CODABLOCKF crashes due to a read global buffer overflow with input
0x1c,0x1c,0x49DOTCODE crashes due to a read-dynamic-stack-buffer-overflow with input
0x28,0x87,0x27:So, I debugged some of the crashes and it seems they only have potential to crash libzint when compiled with address sanitizer.
Last edit: Christian Hartlage 2022-03-23
Dear Christian,
thank you for the repot. I just want to say, that examining the report is on my todo-List.
Thank you,
Harald
Dear Harald,
we also fuzzed the zint library and found some more bugs. All files to reproduce the bugs are in the attachment and you can trigger every bug with the zint command line tool
if you compile it with address sanitizer (-DZINT_SANITIZE=TRUE). All line numbers are from zint-2.7.1
telepent.c - telepen()
In telepen.c
63 char dest[512]; /*14 + 30 * 14 + 14 + 14 + 1 ~ 512 */the dest array is too small because the biggest element in41 static char *TeleTable[]is 16 byte.I think the best solution is to increase thedest[] buffer. (If I calculate it correct
111 char dest[1024];should be large enough)library.c - ZBarcode_Encode()
If you execute zint with an empty file you get a valid buffer of size zero in library.c
1457 buffer = (unsigned char *) malloc(fileLen * sizeof (unsigned char));and then you call995 in_length = (int)ustrlen(source);on that buffer of size zero. Maybe you can return a ZINT_ERROR after1444 fileLen = ftell(file);if the file size is zero.maxicode.c - maxi_text_process()
I think the problem is this part of the code in maxicode.c
in line 454 you check
i <= 143but in line 443 you accesscharacter[i + 5]this overflows ifi >= 139code1.c - c1_encode()
this error occurs in the do while loop in c1_encode()
the check of
sp < lengthin line 1020 is not enough because there are lot ofsource[sp + i](and source[sp + 1|2]) accesses which will overflow ifsp + i >= lengthaztec.c - aztec_text_process()
in aztec.c the memory allocated at lines 139-141
is not freed if you return at line 724 this should be easy to fix, i think you can free all three buffers before line 724
library.c - ZBarcode_Encode_File()
here its the same again the buffer allocated at line 1454 is not freed if you return at line 1469
i think the same can happen at line 1472
dotcode.c
in line 1096 if masked_array[i] is >= 113 memory is read outside of dot_patterns[113]
codeword_array is generated by dotcode_encode_message() at line 1298 in dotcode()
masked_codeword_array is generated by apply_mask() at line 1423 in dotcode()
If the codeword_array should not contain values >= 113 the error is in dotcode_encode_message() (poc creates codeword_array[395] == 233)
If the codeword_array can contain values >= 113 the error is in apply_mask() at 1220 => asked_codeword_array[j + 1] = codeword_array[j] % 113;
pdf417.c - pdf417() / micro_pdf417()
this bug happens with
./zint -b55(pdf417) and./zint -b84(micro_pdf417), maybe the root of this bug is in pdf417_enc(). I tried to understand the problem, but there happens a lot and I didn't get it, sorry.there is another bug in pdf417.c maybe this is related
aztec.c -aztec_text_process()
If I understand it right length in bin_append() and bin_append_posn() is the length of the data you append and not the max length of the buffer
and the bug is in aztec_text_process() where you should guarantee that a call of bin_append() can't overflow your binary_string
I hope this helps you,
Nico
Thank you for finding the time to test Zint so thoroughly. After much effort (mostly from Git Lost) I think all of these bugs have now been sorted out. If Chris or Nico could could please confirm this then I think it would be a relief to close this ticket!
I tested the gitlost-zint 22354a81f12af9f9b68fae4fb48bac8bee93d698 version and run all my test cases and found one more in the dotcode.c. I didn't reported it previously because I thought it was a duplicate of the other dotcode bug. Sorry for that.
This bug is strange I can trigger it only if I compile zint with gcc (version 9.3.0) and asan, with clang and asan I can't reproduce it. The inputs are in the attachment. All inputs trigger the same bug at different locations. Its always an access to codeword_array[array_length] with a too large array_length.
All other bugs are fixed in my opinion, thanks for the replay and your work done here.
Thanks very much Nico, [f51499] should address the DOTCODE
codearrayoverflow.Related
Commit: [f51499]
Last edit: Git Lost 2020-03-31
Yes fr1499 fixed it, I think this ticket can be closed
Git-Lost has confirmed that all found bugs are fixed.
Cudos to all bug-hunters,
Harald