diff options
author | Jeremy Allison <jra@samba.org> | 2016-11-30 09:23:52 -0800 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2016-12-01 05:53:43 +0100 |
commit | 446851c8615721294b2265cddc36007ae450e916 (patch) | |
tree | 234cc5f9419a39126ea86ad5f9b7f07ea79c3178 /librpc/ndr | |
parent | d2fe23ae0a66d781b97ec362bb1524b7c31e38b8 (diff) | |
download | samba-446851c8615721294b2265cddc36007ae450e916.tar.gz |
librpc: cab: Fix ndr_size_cab_file() to detect integer wrap.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Dec 1 05:53:43 CET 2016 on sn-devel-144
Diffstat (limited to 'librpc/ndr')
-rw-r--r-- | librpc/ndr/ndr_cab.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c index d5ab87fb0af..ae95bf45b3b 100644 --- a/librpc/ndr/ndr_cab.c +++ b/librpc/ndr/ndr_cab.c @@ -116,7 +116,7 @@ uint32_t ndr_cab_generate_checksum(const struct CFDATA *r) csumPartial); } -static uint32_t ndr_size_cab_file(const struct cab_file *r) +static bool ndr_size_cab_file(const struct cab_file *r, uint32_t *psize) { uint32_t size = 0; int i; @@ -126,20 +126,39 @@ static uint32_t ndr_size_cab_file(const struct cab_file *r) /* folder */ for (i = 0; i < r->cfheader.cFolders; i++) { + if (size + 8 < size) { + /* Integer wrap. */ + return false; + } size += 8; } /* files */ for (i = 0; i < r->cfheader.cFiles; i++) { - size += ndr_size_CFFILE(&r->cffiles[i], 0); + uint32_t cfsize = ndr_size_CFFILE(&r->cffiles[i], 0); + if (size + cfsize < size) { + /* Integer wrap. */ + return false; + } + size += cfsize; } /* data */ for (i = 0; i < ndr_count_cfdata(r); i++) { - size += 8 + r->cfdata[i].cbData; + if (size + 8 < size) { + /* Integer wrap. */ + return false; + } + size += 8; + if (size + r->cfdata[i].cbData < size) { + /* Integer wrap. */ + return false; + } + size += r->cfdata[i].cbData; } - return size; + *psize = size; + return true; } enum cf_compress_type ndr_cab_get_compression(const struct cab_file *r) @@ -156,6 +175,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags uint32_t cntr_cffolders_0; uint32_t cntr_cffiles_0; uint32_t cntr_cfdata_0; + uint32_t cab_size = 0; { uint32_t _flags_save_STRUCT = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN); @@ -188,7 +208,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags ndr->flags = _flags_save_STRUCT; } - SIVAL(ndr->data, 8, ndr_size_cab_file(r)); + if (ndr_size_cab_file(r, &cab_size) == false) { + return NDR_ERR_VALIDATE; + } + SIVAL(ndr->data, 8, cab_size); return NDR_ERR_SUCCESS; } |