#181 OSS-Fuzz ZBarcode_Encode_File fix, allow for zero-length file, free buffer on error

This commit is contained in:
gitlost 2020-03-26 22:17:37 +00:00
parent 027e8a775d
commit 0f5deccfb6
2 changed files with 79 additions and 8 deletions

View File

@ -1424,13 +1424,14 @@ int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, unsigned char
int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) { int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
FILE *file; FILE *file;
unsigned char *buffer; unsigned char *buffer;
unsigned long fileLen; long fileLen;
unsigned int nRead = 0, n = 0; size_t n;
int nRead = 0;
int ret; int ret;
if (!strcmp(filename, "-")) { if (!strcmp(filename, "-")) {
file = stdin; file = stdin;
fileLen = 7100; fileLen = 7900;
} else { } else {
file = fopen(filename, "rb"); file = fopen(filename, "rb");
if (!file) { if (!file) {
@ -1444,13 +1445,19 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
fileLen = ftell(file); fileLen = ftell(file);
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
if (fileLen > 7100) { if (fileLen > 7900) {
/* The largest amount of data that can be encoded is 7089 numeric digits in QR Code */ /* The largest amount of data that can be encoded is 7827 numeric digits in Han Xin Code */
strcpy(symbol->errtxt, "230: Input file too long"); strcpy(symbol->errtxt, "230: Input file too long");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA); error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
fclose(file); fclose(file);
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (fileLen <= 0) {
strcpy(symbol->errtxt, "235: Input file empty or unseekable");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
fclose(file);
return ZINT_ERROR_INVALID_DATA;
}
} }
/* Allocate memory */ /* Allocate memory */
@ -1458,8 +1465,9 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
if (!buffer) { if (!buffer) {
strcpy(symbol->errtxt, "231: Internal memory error"); strcpy(symbol->errtxt, "231: Internal memory error");
error_tag(symbol->errtxt, ZINT_ERROR_MEMORY); error_tag(symbol->errtxt, ZINT_ERROR_MEMORY);
if (strcmp(filename, "-")) if (strcmp(filename, "-")) {
fclose(file); fclose(file);
}
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
@ -1469,12 +1477,18 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename) {
n = fread(buffer + nRead, 1, fileLen - nRead, file); n = fread(buffer + nRead, 1, fileLen - nRead, file);
if (ferror(file)) { if (ferror(file)) {
strcpy(symbol->errtxt, strerror(errno)); strcpy(symbol->errtxt, strerror(errno));
if (strcmp(filename, "-")) {
fclose(file);
}
free(buffer);
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
nRead += n; nRead += n;
} while (!feof(file) && (0 < n) && (nRead < fileLen)); } while (!feof(file) && (0 < n) && (nRead < fileLen));
if (strcmp(filename, "-")) {
fclose(file); fclose(file);
}
ret = ZBarcode_Encode(symbol, buffer, nRead); ret = ZBarcode_Encode(symbol, buffer, nRead);
free(buffer); free(buffer);
return ret; return ret;

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
@ -30,6 +30,9 @@
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#include "testcommon.h" #include "testcommon.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
static void test_checks(void) static void test_checks(void)
{ {
@ -143,10 +146,64 @@ static void test_input_mode(void)
testFinish(); testFinish();
} }
// #181 Nico Gunkel OSS-Fuzz
static void test_encode_file_zero_length(void)
{
testStart("");
int ret;
char filename[] = "in.bin";
int fd;
struct zint_symbol* symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
(void)remove(filename); // In case junk hanging around
fd = creat(filename, S_IRUSR);
assert_nonzero(fd, "Input file not created\n");
assert_zero(close(fd), "close(%s) != 0\n", filename);
ret = ZBarcode_Encode_File(symbol, filename);
assert_equal(ret, ZINT_ERROR_INVALID_DATA, "ret %d != ZINT_ERROR_INVALID_DATA\n", ret);
assert_zero(remove(filename), "remove(%s) != 0\n", filename);
ZBarcode_Delete(symbol);
testFinish();
}
// #181 Nico Gunkel OSS-Fuzz (buffer not freed on fread() error) Note: unable to reproduce fread() error using this method
static void test_encode_file_directory(void)
{
testStart("");
int ret;
char dirname[] = "in_dir";
int fd;
struct zint_symbol* symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
(void)rmdir(dirname); // In case junk hanging around
assert_zero(mkdir(dirname, 0700), "mkdir(%s, 0700) != 0\n", dirname);
ret = ZBarcode_Encode_File(symbol, dirname);
assert_equal(ret, ZINT_ERROR_INVALID_DATA, "ret %d != ZINT_ERROR_INVALID_DATA (%s)\n", ret, symbol->errtxt);
assert_zero(rmdir(dirname), "rmdir(%s) != 0\n", dirname);
ZBarcode_Delete(symbol);
testFinish();
}
int main() int main()
{ {
test_checks(); test_checks();
test_input_mode(); test_input_mode();
test_encode_file_zero_length();
test_encode_file_directory();
testReport(); testReport();