summaryrefslogtreecommitdiff
path: root/librpc/ndr
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2016-04-22 12:02:57 +1200
committerGarming Sam <garming@samba.org>2016-05-03 08:10:10 +0200
commit98712e9bda29105ae23de487c3261ebf959408c5 (patch)
tree8e6d1d974472b894f339a788304542ddd3c3ef1f /librpc/ndr
parentef0f4654546fdbfdf7165645f4b2291a753bb480 (diff)
downloadsamba-98712e9bda29105ae23de487c3261ebf959408c5.tar.gz
libndr: Add ndr_pull_struct_blob_all_noalloc
This allows us to remove talloc() calls from GUID_from_ndr_blob(). To do this the struct ndr_pull is placed on the stack, and filled in there. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'librpc/ndr')
-rw-r--r--librpc/ndr/libndr.h2
-rw-r--r--librpc/ndr/ndr.c39
-rw-r--r--librpc/ndr/uuid.c12
3 files changed, 44 insertions, 9 deletions
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index a268f128145..10054376eec 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -550,6 +550,8 @@ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p);
uint32_t ndr_pull_steal_switch_value(struct ndr_pull *ndr, const void *p);
enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn);
enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn);
+enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
+ void *p, ndr_pull_flags_fn_t fn);
enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn);
enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn);
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 89bacf7de5f..f66029ab2cb 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -1161,6 +1161,45 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLO
}
/*
+ pull a struct from a blob using NDR - failing if all bytes are not consumed
+
+ This only works for structures with NO allocated memory, like
+ objectSID and GUID. This helps because we parse these a lot.
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
+ void *p, ndr_pull_flags_fn_t fn)
+{
+ /*
+ * We init this structure on the stack here, to avoid a
+ * talloc() as otherwise this call to the fn() is assured not
+ * to be doing any allocation, eg SIDs and GUIDs.
+ *
+ * This allows us to keep the safety of the PIDL-generated
+ * code without the talloc() overhead.
+ */
+ struct ndr_pull ndr = {
+ .data = blob->data,
+ .data_size = blob->length,
+ .current_mem_ctx = (void *)-1
+ };
+ uint32_t highest_ofs;
+ NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ 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);
+ return ret;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
pull a union from a blob using NDR, given the union discriminator
*/
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
diff --git a/librpc/ndr/uuid.c b/librpc/ndr/uuid.c
index 654bebd0d08..9d955abc3d5 100644
--- a/librpc/ndr/uuid.c
+++ b/librpc/ndr/uuid.c
@@ -42,15 +42,9 @@ _PUBLIC_ NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx,
*/
_PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid)
{
- enum ndr_err_code ndr_err;
- TALLOC_CTX *mem_ctx;
-
- mem_ctx = talloc_new(NULL);
- NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
-
- ndr_err = ndr_pull_struct_blob_all(b, mem_ctx, guid,
- (ndr_pull_flags_fn_t)ndr_pull_GUID);
- talloc_free(mem_ctx);
+ enum ndr_err_code ndr_err =
+ ndr_pull_struct_blob_all_noalloc(b, guid,
+ (ndr_pull_flags_fn_t)ndr_pull_GUID);
return ndr_map_error2ntstatus(ndr_err);
}