summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2017-12-12 13:52:57 +0000
committerRichard Hughes <richard@hughsie.com>2017-12-12 14:06:49 +0000
commitcbfff7a2175c7f970761c800411c46eed41129b4 (patch)
tree138f8b2df62baf5c7a1ac43127744dc161d2495d
parentb95728249789fb786dbb68a56d696b92e432aa25 (diff)
downloadgcab-cbfff7a2175c7f970761c800411c46eed41129b4.tar.gz
trivial: Fix the endian checksum calculation in a better way
Fixes issues like https://bugs.launchpad.net/ubuntu/+source/gcab/+bug/1737723 when decompressing a small firmware file.
-rw-r--r--libgcab/cabinet.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/libgcab/cabinet.c b/libgcab/cabinet.c
index caf695e..8c944d0 100644
--- a/libgcab/cabinet.c
+++ b/libgcab/cabinet.c
@@ -421,8 +421,14 @@ cdata_write (cdata_t *cd, GDataOutputStream *out, int type,
return FALSE;
guint32 datacsum = compute_checksum(cd->in, cd->ncbytes, 0);
- guint32 sizecsum = GUINT32_TO_LE(cd->ncbytes << 16 | cd->nubytes);
- cd->checksum = compute_checksum ((guint8*)&sizecsum, 4, datacsum);
+ guint8 sizecsum[4];
+ guint16 nbytes_le;
+
+ nbytes_le = GUINT16_TO_LE (cd->ncbytes);
+ memcpy (&sizecsum[0], &nbytes_le, 2);
+ nbytes_le = GUINT16_TO_LE (cd->nubytes);
+ memcpy (&sizecsum[2], &nbytes_le, 2);
+ cd->checksum = compute_checksum (sizecsum, sizeof(sizecsum), datacsum);
GOutputStream *stream = g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (out));
*bytes_written = 0;
@@ -465,7 +471,8 @@ cdata_read (cdata_t *cd, guint8 res_data, gint comptype,
gint compression = comptype & GCAB_COMPRESSION_MASK;
guint8 *buf = compression == GCAB_COMPRESSION_NONE ? cd->out : cd->in;
guint32 datacsum;
- guint32 sizecsum;
+ guint8 sizecsum[4];
+ guint16 nbytes_le;
if (compression > GCAB_COMPRESSION_MSZIP &&
compression != GCAB_COMPRESSION_LZX) {
@@ -482,8 +489,11 @@ cdata_read (cdata_t *cd, guint8 res_data, gint comptype,
RN (buf, cd->ncbytes);
datacsum = compute_checksum(buf, cd->ncbytes, 0);
- sizecsum = GUINT32_TO_LE(cd->ncbytes << 16 | cd->nubytes);
- if (cd->checksum != compute_checksum ((guint8*)&sizecsum, 4, datacsum)) {
+ nbytes_le = GUINT16_TO_LE (cd->ncbytes);
+ memcpy (&sizecsum[0], &nbytes_le, 2);
+ nbytes_le = GUINT16_TO_LE (cd->nubytes);
+ memcpy (&sizecsum[2], &nbytes_le, 2);
+ if (cd->checksum != compute_checksum (sizecsum, sizeof(sizecsum), datacsum)) {
g_set_error_literal (error, GCAB_ERROR, GCAB_ERROR_FAILED,
_("incorrect checksum detected"));
return FALSE;