summaryrefslogtreecommitdiff
path: root/librpc/ndr
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2016-11-30 09:23:52 -0800
committerJeremy Allison <jra@samba.org>2016-12-01 05:53:43 +0100
commit446851c8615721294b2265cddc36007ae450e916 (patch)
tree234cc5f9419a39126ea86ad5f9b7f07ea79c3178 /librpc/ndr
parentd2fe23ae0a66d781b97ec362bb1524b7c31e38b8 (diff)
downloadsamba-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.c33
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;
}