diff options
author | Andrew Bartlett <abartlet@samba.org> | 2016-04-22 12:02:57 +1200 |
---|---|---|
committer | Garming Sam <garming@samba.org> | 2016-05-03 08:10:10 +0200 |
commit | 98712e9bda29105ae23de487c3261ebf959408c5 (patch) | |
tree | 8e6d1d974472b894f339a788304542ddd3c3ef1f /librpc/ndr | |
parent | ef0f4654546fdbfdf7165645f4b2291a753bb480 (diff) | |
download | samba-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.h | 2 | ||||
-rw-r--r-- | librpc/ndr/ndr.c | 39 | ||||
-rw-r--r-- | librpc/ndr/uuid.c | 12 |
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); } |