librpc/ndr: remember the highest offset we parsed with relative pointer buffers
authorStefan Metzmacher <metze@samba.org>
Fri, 20 Nov 2009 10:34:53 +0000 (11:34 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 20 Nov 2009 12:48:35 +0000 (13:48 +0100)
ndr_*_pull_blob_all() will now work if relative pointers are used.

metze

librpc/ndr/libndr.h
librpc/ndr/ndr.c

index 45cb24405f3c3af0602745098244b2d88893eb99..e881a5c691d579022c0e7065d79b4d32a6605c3b 100644 (file)
@@ -62,6 +62,7 @@ struct ndr_pull {
 
        struct smb_iconv_convenience *iconv_convenience;
 
+       uint32_t relative_highest_offset;
        uint32_t relative_base_offset;
        struct ndr_token_list *relative_base_list;
 
index cb47ca1d60bb6130a71c90e4568930eea66bdb8b..1969decb5b866925c4e6e399f128d00e9580b45c 100644 (file)
@@ -861,13 +861,22 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLO
                                                    void *p, ndr_pull_flags_fn_t fn)
 {
        struct ndr_pull *ndr;
+       uint32_t highest_ofs;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
        NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
-       if (ndr->offset < ndr->data_size) {
-               return ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
-                                     "not all bytes consumed ofs[%u] size[%u]",
-                                     ndr->offset, ndr->data_size);
+       if (ndr->offset > ndr->relative_highest_offset) {
+               highest_ofs = ndr->offset;
+       } else {
+               highest_ofs = ndr->relative_highest_offset;
+       }
+       if (highest_ofs < ndr->data_size) {
+               enum ndr_err_code ret;
+               ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
+                                    "not all bytes consumed ofs[%u] size[%u]",
+                                    highest_ofs, ndr->data_size);
+               talloc_free(ndr);
+               return ret;
        }
        talloc_free(ndr);
        return NDR_ERR_SUCCESS;
@@ -898,15 +907,21 @@ _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC
                             uint32_t level, ndr_pull_flags_fn_t fn)
 {
        struct ndr_pull *ndr;
+       uint32_t highest_ofs;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
        NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
        NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
-       if (ndr->offset < ndr->data_size) {
+       if (ndr->offset > ndr->relative_highest_offset) {
+               highest_ofs = ndr->offset;
+       } else {
+               highest_ofs = ndr->relative_highest_offset;
+       }
+       if (highest_ofs < ndr->data_size) {
                enum ndr_err_code ret;
                ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
                                     "not all bytes consumed ofs[%u] size[%u]",
-                                    ndr->offset, ndr->data_size);
+                                    highest_ofs, ndr->data_size);
                talloc_free(ndr);
                return ret;
        }