diff options
author | Richard Hughes <richard@hughsie.com> | 2017-12-12 13:52:57 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2017-12-12 14:06:49 +0000 |
commit | cbfff7a2175c7f970761c800411c46eed41129b4 (patch) | |
tree | 138f8b2df62baf5c7a1ac43127744dc161d2495d | |
parent | b95728249789fb786dbb68a56d696b92e432aa25 (diff) | |
download | gcab-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.c | 20 |
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; |