diff --git a/libgcab/cabinet.c b/libgcab/cabinet.c
index a675d1b..9847f1c 100644
--- a/libgcab/cabinet.c
+++ b/libgcab/cabinet.c
@@ -460,18 +460,38 @@ cdata_read (cdata_t *cd, u1 res_data, gint comptype,
gboolean success = FALSE;
int ret, zret = Z_OK;
gint compression = comptype & GCAB_COMPRESSION_MASK;
- guint8 *buf = compression == GCAB_COMPRESSION_NONE ? cd->out : cd->in;
+ gsize buf_sz;
+ guint8 *buf = NULL;
CHECKSUM datacsum;
- if (compression > GCAB_COMPRESSION_MSZIP &&
- compression != GCAB_COMPRESSION_LZX) {
+ /* decompress directly into ->out for no decompression */
+ switch (compression) {
+ case GCAB_COMPRESSION_NONE:
+ buf = cd->out;
+ buf_sz = sizeof(cd->out);
+ break;
+ case GCAB_COMPRESSION_MSZIP:
+ case GCAB_COMPRESSION_LZX:
+ buf = cd->in;
+ buf_sz = sizeof(cd->in);
+ break;
+ default:
g_set_error (error, GCAB_ERROR, GCAB_ERROR_FAILED,
_("unsupported compression method %d"), compression);
- return FALSE;
+ break;
}
+ if (buf == NULL)
+ return FALSE;
R4 (cd->checksum);
R2 (cd->ncbytes);
+ if (cd->ncbytes > buf_sz) {
+ g_set_error (error, GCAB_ERROR, GCAB_ERROR_FAILED,
+ "tried to decompress %" G_GUINT16_FORMAT " bytes "
+ "into buffer of size %" G_GSIZE_FORMAT,
+ cd->ncbytes, buf_sz);
+ return FALSE;
+ }
R2 (cd->nubytes);
cd->reserved = g_malloc (res_data);
RN (cd->reserved, res_data);