Permalink
Browse files

Add checking of CRC from common extended header.

  • Loading branch information...
1 parent 194245c commit ac7b0f52ba2fe7dd6225aeb764bc34326b99ee65 @fragglet committed Apr 14, 2012
Showing with 61 additions and 5 deletions.
  1. +31 −1 lib/ext_common.c
  2. +2 −0 lib/ext_header.c
  3. +1 −0 lib/ext_header.h
  4. +25 −4 lib/lha_file_header.c
  5. +2 −0 lib/lha_file_header.h
View
@@ -22,6 +22,36 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <ctype.h>
#include "ext_header.h"
+#include "lha_endian.h"
+
+static int ext_header_common_decoder(LHAFileHeader *header,
+ uint8_t *data,
+ size_t data_len)
+{
+ header->extra_flags |= LHA_FILE_COMMON_CRC;
+ header->common_crc = lha_decode_uint16(data);
+
+ // There is a catch-22 in calculating the CRC, because the field
+ // containing the CRC is part of the data being CRC'd. The solution
+ // is that the CRC is calculated with the CRC field set to zero.
+ // Therefore, now that the CRC has been read, set the field to
+ // zero in the raw_data array so that the CRC can be calculated
+ // correctly.
+
+ data[0] = 0x00;
+ data[1] = 0x00;
+
+ // TODO: Some platforms (OS/2, Unix) put extra data in the common
+ // header which might also be decoded.
+
+ return 1;
+}
+
+LHAExtHeaderType lha_ext_header_common = {
+ LHA_EXT_HEADER_COMMON,
+ ext_header_common_decoder,
+ 2
+};
static int ext_header_filename_decoder(LHAFileHeader *header,
uint8_t *data,
@@ -70,7 +100,7 @@ static int ext_header_path_decoder(LHAFileHeader *header,
// separator at the end of the string. This is broken (and
// was fixed in a later version), but handle it correctly.
- if (data_len > 0 && new_path[data_len - 1] != 0xff) {
+ if (new_path[data_len - 1] != 0xff) {
new_path[data_len] = 0xff;
new_path[data_len + 1] = '\0';
++data_len;
View
@@ -22,6 +22,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ext_common.c:
+extern LHAExtHeaderType lha_ext_header_common;
extern LHAExtHeaderType lha_ext_header_filename;
extern LHAExtHeaderType lha_ext_header_path;
@@ -34,6 +35,7 @@ extern LHAExtHeaderType lha_ext_header_unix_group;
extern LHAExtHeaderType lha_ext_header_unix_timestamp;
static const LHAExtHeaderType *ext_header_types[] = {
+ &lha_ext_header_common,
&lha_ext_header_filename,
&lha_ext_header_path,
&lha_ext_header_unix_perms,
View
@@ -27,6 +27,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// Extended header types:
+#define LHA_EXT_HEADER_COMMON 0x00
#define LHA_EXT_HEADER_FILENAME 0x01
#define LHA_EXT_HEADER_PATH 0x02
#define LHA_EXT_HEADER_MULTI_DISC 0x39
View
@@ -26,6 +26,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "lha_endian.h"
#include "lha_file_header.h"
#include "ext_header.h"
+#include "crc16.h"
#define COMMON_HEADER_LEN 22 /* bytes */
#define LEVEL_0_MIN_HEADER_LEN 22 /* bytes */
@@ -37,7 +38,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// Perform checksum of header contents.
-static int checksum_header(uint8_t *header, size_t header_len, size_t csum)
+static int check_l0_checksum(uint8_t *header, size_t header_len, size_t csum)
{
unsigned int result;
unsigned int i;
@@ -51,6 +52,18 @@ static int checksum_header(uint8_t *header, size_t header_len, size_t csum)
return (result & 0xff) == csum;
}
+// Perform full-header CRC check, based on CRC from "common" extended header.
+
+static int check_common_crc(LHAFileHeader *header)
+{
+ uint16_t crc;
+
+ crc = 0;
+ lha_crc16_buf(&crc, header->raw_data, header->raw_data_len);
+
+ return crc == header->common_crc;
+}
+
// Decode MS-DOS timestamp.
static unsigned int decode_ftime(uint8_t *buf)
@@ -376,9 +389,9 @@ static int decode_level0_header(LHAFileHeader **header, LHAInputStream *stream)
// Checksum the header.
- if (!checksum_header(&RAW_DATA(header, 2),
- RAW_DATA_LEN(header) - 2,
- header_csum)) {
+ if (!check_l0_checksum(&RAW_DATA(header, 2),
+ RAW_DATA_LEN(header) - 2,
+ header_csum)) {
return 0;
}
@@ -578,6 +591,14 @@ LHAFileHeader *lha_file_header_read(LHAInputStream *stream)
fix_msdos_allcaps(header);
}
+ // Was the "common" extended header read, which contains a CRC of
+ // the full header? If so, perform a CRC check now.
+
+ if ((header->extra_flags & LHA_FILE_COMMON_CRC) != 0
+ && !check_common_crc(header)) {
+ return 0;
+ }
+
return header;
fail:
lha_file_header_free(header);
View
@@ -26,6 +26,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define LHA_FILE_UNIX_PERMS 0x01
#define LHA_FILE_UNIX_UID_GID 0x02
+#define LHA_FILE_COMMON_CRC 0x04
// Common OS types:
@@ -91,6 +92,7 @@ struct _LHAFileHeader {
unsigned int unix_gid;
char *unix_group;
char *unix_username;
+ uint16_t common_crc;
};
/**

0 comments on commit ac7b0f5

Please sign in to comment.