clamav/libclamav/tiff.c

166 lines
5.2 KiB
C
Raw Normal View History

/*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* Authors: Kevin Lin <kevlin2@cisco.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include "others.h"
#include "tiff.h"
#define tiff32_to_host(be,x) (be ? be32_to_host(x) : le32_to_host(x))
#define tiff16_to_host(be,x) (be ? be16_to_host(x) : le16_to_host(x))
struct tiff_ifd {
uint16_t tag;
uint16_t type;
uint32_t numval;
uint32_t value;
};
int cli_parsetiff(cli_ctx *ctx)
{
fmap_t *map = *ctx->fmap;
unsigned char magic[4];
int big_endian;
uint32_t offset = 0, ifd_count = 0;
uint16_t i, num_entries;
struct tiff_ifd entry;
size_t value_size;
cli_dbgmsg("in cli_parsetiff()\n");
/* check the magic */
if(fmap_readn(map, magic, offset, 4) != 4)
return CL_SUCCESS;
offset += 4;
if(!memcmp(magic, "\x4d\x4d\x00\x2a", 4))
big_endian = 1;
else if(!memcmp(magic, "\x49\x49\x2a\x00", 4))
big_endian = 0;
else
return CL_SUCCESS; /* Not a TIFF file */
cli_dbgmsg("cli_parsetiff: %s-endian tiff file\n", big_endian ? "big" : "little");
/* acquire offset of first IFD */
if(fmap_readn(map, &offset, offset, 4) != 4)
return CL_EPARSE;
offset = tiff32_to_host(big_endian, offset);
cli_dbgmsg("cli_parsetiff: first IFD located @ offset %u\n", offset);
if(!offset) {
cli_errmsg("cli_parsetiff: invalid offset for first IFD\n");
return CL_EPARSE;
}
/* each IFD represents a subfile, though only the first one normally matters */
do {
/* acquire number of directory entries in current IFD */
if(fmap_readn(map, &num_entries, offset, 2) != 2)
return CL_EPARSE;
offset += 2;
num_entries = tiff16_to_host(big_endian, num_entries);
cli_dbgmsg("cli_parsetiff: IFD %u declared %u directory entries\n", ifd_count, num_entries);
Spelling Adjustments (#30) * spelling: accessed * spelling: alignment * spelling: amalgamated * spelling: answers * spelling: another * spelling: acquisition * spelling: apitid * spelling: ascii * spelling: appending * spelling: appropriate * spelling: arbitrary * spelling: architecture * spelling: asynchronous * spelling: attachments * spelling: argument * spelling: authenticode * spelling: because * spelling: boundary * spelling: brackets * spelling: bytecode * spelling: calculation * spelling: cannot * spelling: changes * spelling: check * spelling: children * spelling: codegen * spelling: commands * spelling: container * spelling: concatenated * spelling: conditions * spelling: continuous * spelling: conversions * spelling: corresponding * spelling: corrupted * spelling: coverity * spelling: crafting * spelling: daemon * spelling: definition * spelling: delivered * spelling: delivery * spelling: delimit * spelling: dependencies * spelling: dependency * spelling: detection * spelling: determine * spelling: disconnects * spelling: distributed * spelling: documentation * spelling: downgraded * spelling: downloading * spelling: endianness * spelling: entities * spelling: especially * spelling: empty * spelling: expected * spelling: explicitly * spelling: existent * spelling: finished * spelling: flexibility * spelling: flexible * spelling: freshclam * spelling: functions * spelling: guarantee * spelling: hardened * spelling: headaches * spelling: heighten * spelling: improper * spelling: increment * spelling: indefinitely * spelling: independent * spelling: inaccessible * spelling: infrastructure Conflicts: docs/html/node68.html * spelling: initializing * spelling: inited * spelling: instream * spelling: installed * spelling: initialization * spelling: initialize * spelling: interface * spelling: intrinsics * spelling: interpreter * spelling: introduced * spelling: invalid * spelling: latency * spelling: lawyers * spelling: libclamav * spelling: likelihood * spelling: loop * spelling: maximum * spelling: million * spelling: milliseconds * spelling: minimum * spelling: minzhuan * spelling: multipart * spelling: misled * spelling: modifiers * spelling: notifying * spelling: objects * spelling: occurred * spelling: occurs * spelling: occurrences * spelling: optimization * spelling: original * spelling: originated * spelling: output * spelling: overridden * spelling: parenthesis * spelling: partition * spelling: performance * spelling: permission * spelling: phishing * spelling: portions * spelling: positives * spelling: preceded * spelling: properties * spelling: protocol * spelling: protos * spelling: quarantine * spelling: recursive * spelling: referring * spelling: reorder * spelling: reset * spelling: resources * spelling: resume * spelling: retrieval * spelling: rewrite * spelling: sanity * spelling: scheduled * spelling: search * spelling: section * spelling: separator * spelling: separated * spelling: specify * spelling: special * spelling: statement * spelling: streams * spelling: succession * spelling: suggests * spelling: superfluous * spelling: suspicious * spelling: synonym * spelling: temporarily * spelling: testfiles * spelling: transverse * spelling: turkish * spelling: typos * spelling: unable * spelling: unexpected * spelling: unexpectedly * spelling: unfinished * spelling: unfortunately * spelling: uninitialized * spelling: unlocking * spelling: unnecessary * spelling: unpack * spelling: unrecognized * spelling: unsupported * spelling: usable * spelling: wherever * spelling: wishlist * spelling: white * spelling: infrastructure * spelling: directories * spelling: overridden * spelling: permission * spelling: yesterday * spelling: initialization * spelling: intrinsics * space adjustment for spelling changes * minor modifications by klin
2018-02-21 15:00:59 -05:00
/* transverse IFD entries */
for(i = 0; i < num_entries; i++) {
if(fmap_readn(map, &entry, offset, sizeof(entry)) != sizeof(entry))
return CL_EPARSE;
offset += sizeof(entry);
entry.tag = tiff16_to_host(big_endian, entry.tag);
entry.type = tiff16_to_host(big_endian, entry.type);
entry.numval = tiff32_to_host(big_endian, entry.numval);
entry.value = tiff32_to_host(big_endian, entry.value);
//cli_dbgmsg("%02u: %u %u %u %u\n", i, entry.tag, entry.type, entry.numval, entry.value);
value_size = entry.numval;
switch(entry.type) {
case 1: /* BYTE */
value_size *= 1;
break;
Spelling Adjustments (#30) * spelling: accessed * spelling: alignment * spelling: amalgamated * spelling: answers * spelling: another * spelling: acquisition * spelling: apitid * spelling: ascii * spelling: appending * spelling: appropriate * spelling: arbitrary * spelling: architecture * spelling: asynchronous * spelling: attachments * spelling: argument * spelling: authenticode * spelling: because * spelling: boundary * spelling: brackets * spelling: bytecode * spelling: calculation * spelling: cannot * spelling: changes * spelling: check * spelling: children * spelling: codegen * spelling: commands * spelling: container * spelling: concatenated * spelling: conditions * spelling: continuous * spelling: conversions * spelling: corresponding * spelling: corrupted * spelling: coverity * spelling: crafting * spelling: daemon * spelling: definition * spelling: delivered * spelling: delivery * spelling: delimit * spelling: dependencies * spelling: dependency * spelling: detection * spelling: determine * spelling: disconnects * spelling: distributed * spelling: documentation * spelling: downgraded * spelling: downloading * spelling: endianness * spelling: entities * spelling: especially * spelling: empty * spelling: expected * spelling: explicitly * spelling: existent * spelling: finished * spelling: flexibility * spelling: flexible * spelling: freshclam * spelling: functions * spelling: guarantee * spelling: hardened * spelling: headaches * spelling: heighten * spelling: improper * spelling: increment * spelling: indefinitely * spelling: independent * spelling: inaccessible * spelling: infrastructure Conflicts: docs/html/node68.html * spelling: initializing * spelling: inited * spelling: instream * spelling: installed * spelling: initialization * spelling: initialize * spelling: interface * spelling: intrinsics * spelling: interpreter * spelling: introduced * spelling: invalid * spelling: latency * spelling: lawyers * spelling: libclamav * spelling: likelihood * spelling: loop * spelling: maximum * spelling: million * spelling: milliseconds * spelling: minimum * spelling: minzhuan * spelling: multipart * spelling: misled * spelling: modifiers * spelling: notifying * spelling: objects * spelling: occurred * spelling: occurs * spelling: occurrences * spelling: optimization * spelling: original * spelling: originated * spelling: output * spelling: overridden * spelling: parenthesis * spelling: partition * spelling: performance * spelling: permission * spelling: phishing * spelling: portions * spelling: positives * spelling: preceded * spelling: properties * spelling: protocol * spelling: protos * spelling: quarantine * spelling: recursive * spelling: referring * spelling: reorder * spelling: reset * spelling: resources * spelling: resume * spelling: retrieval * spelling: rewrite * spelling: sanity * spelling: scheduled * spelling: search * spelling: section * spelling: separator * spelling: separated * spelling: specify * spelling: special * spelling: statement * spelling: streams * spelling: succession * spelling: suggests * spelling: superfluous * spelling: suspicious * spelling: synonym * spelling: temporarily * spelling: testfiles * spelling: transverse * spelling: turkish * spelling: typos * spelling: unable * spelling: unexpected * spelling: unexpectedly * spelling: unfinished * spelling: unfortunately * spelling: uninitialized * spelling: unlocking * spelling: unnecessary * spelling: unpack * spelling: unrecognized * spelling: unsupported * spelling: usable * spelling: wherever * spelling: wishlist * spelling: white * spelling: infrastructure * spelling: directories * spelling: overridden * spelling: permission * spelling: yesterday * spelling: initialization * spelling: intrinsics * space adjustment for spelling changes * minor modifications by klin
2018-02-21 15:00:59 -05:00
case 2: /* ASCII */
value_size *= 1;
break;
case 3: /* SHORT */
value_size *= 2;
break;
case 4: /* LONG */
value_size *= 4;
break;
case 5: /* RATIONAL (LONG/LONG) */
value_size *= 8;
break;
/* TIFF 6.0 Types */
case 6: /* SBYTE */
value_size *= 1;
break;
case 7: /* UNDEFINED */
value_size *= 1;
break;
case 8: /* SSHORT */
value_size *= 2;
break;
case 9: /* SLONG */
value_size *= 4;
break;
case 10: /* SRATIONAL (SLONG/SLONG) */
value_size *= 8;
break;
case 11: /* FLOAT */
value_size *= 4;
break;
case 12: /* DOUBLE */
value_size *= 8;
break;
default: /* INVALID or NEW Type */
value_size *= 0;
break;
}
if(value_size > sizeof(entry.value)) {
if(entry.value + value_size > map->len) {
cli_warnmsg("cli_parsetiff: TFD entry field %u exceeds bounds of TIFF file [%llu > %llu]\n",
i, (long long unsigned)(entry.value + value_size), (long long unsigned)map->len);
return cli_append_virus(ctx, "Heuristics.TIFF.OutOfBoundsAccess");
}
}
}
ifd_count++;
/* acquire next IFD location, gets 0 if last IFD */
if(fmap_readn(map, &offset, offset, sizeof(offset)) != sizeof(offset))
return CL_EPARSE;
offset = tiff32_to_host(big_endian, offset);
} while(offset);
cli_dbgmsg("cli_parsetiff: examined %u IFD(s)\n", ifd_count);
return CL_SUCCESS;
}